diff options
author | Andras Becsi <andras.becsi@digia.com> | 2013-12-11 21:33:03 +0100 |
---|---|---|
committer | Andras Becsi <andras.becsi@digia.com> | 2013-12-13 12:34:07 +0100 |
commit | f2a33ff9cbc6d19943f1c7fbddd1f23d23975577 (patch) | |
tree | 0586a32aa390ade8557dfd6b4897f43a07449578 /chromium/ui | |
parent | 5362912cdb5eea702b68ebe23702468d17c3017a (diff) | |
download | qtwebengine-chromium-f2a33ff9cbc6d19943f1c7fbddd1f23d23975577.tar.gz |
Update Chromium to branch 1650 (31.0.1650.63)
Change-Id: I57d8c832eaec1eb2364e0a8e7352a6dd354db99f
Reviewed-by: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
Diffstat (limited to 'chromium/ui')
1087 files changed, 19086 insertions, 15631 deletions
diff --git a/chromium/ui/OWNERS b/chromium/ui/OWNERS index b88f27bdc51..585112d131a 100644 --- a/chromium/ui/OWNERS +++ b/chromium/ui/OWNERS @@ -4,6 +4,12 @@ sky@chromium.org # Mac stuff thakis@chromium.org +# Android +per-file *android*=bulach@chromium.org +per-file *android*=tedchoc@chromium.org +per-file *android*=yfriedman@chromium.org +per-file *android*=newt@chromium.org + per-file *.isolate=csharp@chromium.org per-file *.isolate=maruel@chromium.org diff --git a/chromium/ui/android/java/WindowOpenDisposition.template b/chromium/ui/android/java/WindowOpenDisposition.template deleted file mode 100644 index 91be4d9536f..00000000000 --- a/chromium/ui/android/java/WindowOpenDisposition.template +++ /dev/null @@ -1,11 +0,0 @@ -// 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. - -package org.chromium.ui; - -public class WindowOpenDisposition { -#define WINDOW_OPEN_DISPOSITION(label, value) public static final int label = value; -#include "ui/base/window_open_disposition_list.h" -#undef WINDOW_OPEN_DISPOSITION -}
\ No newline at end of file diff --git a/chromium/ui/android/java/res/drawable-hdpi/autofill_popup_background_down.9.png b/chromium/ui/android/java/res/drawable-hdpi/autofill_popup_background_down.9.png Binary files differdeleted file mode 100644 index 62478fcf66c..00000000000 --- a/chromium/ui/android/java/res/drawable-hdpi/autofill_popup_background_down.9.png +++ /dev/null diff --git a/chromium/ui/android/java/res/drawable-hdpi/autofill_popup_background_up.9.png b/chromium/ui/android/java/res/drawable-hdpi/autofill_popup_background_up.9.png Binary files differdeleted file mode 100644 index 290f5260677..00000000000 --- a/chromium/ui/android/java/res/drawable-hdpi/autofill_popup_background_up.9.png +++ /dev/null diff --git a/chromium/ui/android/java/res/drawable-hdpi/color_picker_advanced_select_handle.png b/chromium/ui/android/java/res/drawable-hdpi/color_picker_advanced_select_handle.png Binary files differdeleted file mode 100644 index be2dc681114..00000000000 --- a/chromium/ui/android/java/res/drawable-hdpi/color_picker_advanced_select_handle.png +++ /dev/null diff --git a/chromium/ui/android/java/res/drawable-ldpi/autofill_popup_background_down.9.png b/chromium/ui/android/java/res/drawable-ldpi/autofill_popup_background_down.9.png Binary files differdeleted file mode 100644 index 0fb3b87b8fd..00000000000 --- a/chromium/ui/android/java/res/drawable-ldpi/autofill_popup_background_down.9.png +++ /dev/null diff --git a/chromium/ui/android/java/res/drawable-ldpi/autofill_popup_background_up.9.png b/chromium/ui/android/java/res/drawable-ldpi/autofill_popup_background_up.9.png Binary files differdeleted file mode 100644 index 4ab1786471b..00000000000 --- a/chromium/ui/android/java/res/drawable-ldpi/autofill_popup_background_up.9.png +++ /dev/null diff --git a/chromium/ui/android/java/res/drawable-nodpi/divider_horizontal_bright.9.png b/chromium/ui/android/java/res/drawable-nodpi/divider_horizontal_bright.9.png Binary files differdeleted file mode 100644 index 24f2a3f1fa4..00000000000 --- a/chromium/ui/android/java/res/drawable-nodpi/divider_horizontal_bright.9.png +++ /dev/null diff --git a/chromium/ui/android/java/res/drawable-xhdpi/autofill_popup_background_down.9.png b/chromium/ui/android/java/res/drawable-xhdpi/autofill_popup_background_down.9.png Binary files differdeleted file mode 100644 index ab4d02cd382..00000000000 --- a/chromium/ui/android/java/res/drawable-xhdpi/autofill_popup_background_down.9.png +++ /dev/null diff --git a/chromium/ui/android/java/res/drawable-xhdpi/autofill_popup_background_up.9.png b/chromium/ui/android/java/res/drawable-xhdpi/autofill_popup_background_up.9.png Binary files differdeleted file mode 100644 index cf3f9e65264..00000000000 --- a/chromium/ui/android/java/res/drawable-xhdpi/autofill_popup_background_up.9.png +++ /dev/null diff --git a/chromium/ui/android/java/res/drawable-xhdpi/color_picker_advanced_select_handle.png b/chromium/ui/android/java/res/drawable-xhdpi/color_picker_advanced_select_handle.png Binary files differdeleted file mode 100644 index 058b30b731b..00000000000 --- a/chromium/ui/android/java/res/drawable-xhdpi/color_picker_advanced_select_handle.png +++ /dev/null diff --git a/chromium/ui/android/java/res/drawable/autofill_popup_background.xml b/chromium/ui/android/java/res/drawable/autofill_popup_background.xml deleted file mode 100644 index 0f8d38babdf..00000000000 --- a/chromium/ui/android/java/res/drawable/autofill_popup_background.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<!-- 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. ---> - -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_above_anchor="true" - android:drawable="@drawable/autofill_popup_background_up" /> - <item android:drawable="@drawable/autofill_popup_background_down" /> -</selector>
\ No newline at end of file diff --git a/chromium/ui/android/java/res/drawable/autofill_popup_background_down.9.png b/chromium/ui/android/java/res/drawable/autofill_popup_background_down.9.png Binary files differdeleted file mode 100644 index 2022fd74388..00000000000 --- a/chromium/ui/android/java/res/drawable/autofill_popup_background_down.9.png +++ /dev/null diff --git a/chromium/ui/android/java/res/drawable/autofill_popup_background_up.9.png b/chromium/ui/android/java/res/drawable/autofill_popup_background_up.9.png Binary files differdeleted file mode 100644 index 62fc5a6bf98..00000000000 --- a/chromium/ui/android/java/res/drawable/autofill_popup_background_up.9.png +++ /dev/null diff --git a/chromium/ui/android/java/res/drawable/color_picker_advanced_select_handle.png b/chromium/ui/android/java/res/drawable/color_picker_advanced_select_handle.png Binary files differdeleted file mode 100644 index 3cdca907c95..00000000000 --- a/chromium/ui/android/java/res/drawable/color_picker_advanced_select_handle.png +++ /dev/null diff --git a/chromium/ui/android/java/res/drawable/color_picker_border.xml b/chromium/ui/android/java/res/drawable/color_picker_border.xml deleted file mode 100644 index b48be9bb41c..00000000000 --- a/chromium/ui/android/java/res/drawable/color_picker_border.xml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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. ---> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - <solid android:color="#00000000"/> - <stroke android:width="1px" android:color="@color/color_picker_border_color" /> -</shape>
\ No newline at end of file diff --git a/chromium/ui/android/java/res/layout/autofill_text.xml b/chromium/ui/android/java/res/layout/autofill_text.xml deleted file mode 100644 index 4a69862a916..00000000000 --- a/chromium/ui/android/java/res/layout/autofill_text.xml +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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. ---> - -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/autofill_menu_text" - android:layout_width="fill_parent" - android:layout_height="44dp" - android:minHeight="44dp" - android:orientation="vertical" - android:gravity="center_vertical"> - <TextView android:id="@+id/autofill_label" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:ellipsize="end" - android:singleLine="true" - android:textSize="18sp" - android:includeFontPadding="false" - android:layout_marginStart="10dp" - android:layout_marginEnd="10dp"/> - <TextView android:id="@+id/autofill_sublabel" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textSize="14sp" - android:textColor="#8b8b8b" - android:ellipsize="end" - android:singleLine="true" - android:includeFontPadding="false" - android:layout_marginStart="10dp" - android:layout_marginEnd="10dp"/> -</LinearLayout> diff --git a/chromium/ui/android/java/res/layout/color_picker_advanced_component.xml b/chromium/ui/android/java/res/layout/color_picker_advanced_component.xml deleted file mode 100644 index a51c055b1b1..00000000000 --- a/chromium/ui/android/java/res/layout/color_picker_advanced_component.xml +++ /dev/null @@ -1,46 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - 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. ---> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="wrap_content" - android:layout_height="wrap_content"> - - <TextView - android:id="@+id/text" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginStart="@dimen/color_picker_gradient_margin" - android:layout_marginEnd="@dimen/color_picker_gradient_margin" - android:textAppearance="@android:style/TextAppearance.Medium" - android:textIsSelectable="false" /> - - <FrameLayout - android:id="@+id/gradient_border" - android:layout_width="match_parent" - android:layout_height="50dp" - android:layout_below="@id/text" - android:layout_marginStart="@dimen/color_picker_gradient_margin" - android:layout_marginEnd="@dimen/color_picker_gradient_margin" - android:layout_marginTop="3dp" - android:background="@drawable/color_picker_border" - android:padding="1dp" > - - <View - android:id="@+id/gradient" - android:layout_width="match_parent" - android:layout_height="match_parent" /> - </FrameLayout> - - <SeekBar - android:id="@+id/seek_bar" - android:layout_width="match_parent" - android:layout_height="75dp" - android:layout_below="@id/text" - android:progressDrawable="@android:color/transparent" - android:thumb="@drawable/color_picker_advanced_select_handle" - android:translationY="25dp" /> - -</RelativeLayout>
\ No newline at end of file diff --git a/chromium/ui/android/java/res/layout/color_picker_dialog_content.xml b/chromium/ui/android/java/res/layout/color_picker_dialog_content.xml deleted file mode 100644 index 8aa4dbaeffd..00000000000 --- a/chromium/ui/android/java/res/layout/color_picker_dialog_content.xml +++ /dev/null @@ -1,56 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - 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. ---> -<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical" - android:padding="15dp"> - - <org.chromium.ui.ColorPickerAdvanced - android:id="@+id/color_picker_advanced" - android:layout_width="match_parent" - android:layout_height="wrap_content" /> - - <FrameLayout - android:id="@+id/color_picker_simple_border" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="@drawable/color_picker_border" - android:paddingStart="1px" - android:paddingEnd="1px" - android:paddingTop="1px"> - - <org.chromium.ui.ColorPickerSimple - android:id="@+id/color_picker_simple" - android:layout_width="match_parent" - android:layout_height="100dp"/> - </FrameLayout> - - <FrameLayout - android:id="@+id/more_colors_button_border" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_below="@+id/color_picker_simple_border" - android:background="@drawable/color_picker_border" - android:padding="1px"> - - <org.chromium.ui.ColorPickerMoreButton - android:id="@+id/more_colors_button" - style="?android:attr/buttonBarButtonStyle" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:minHeight="48dp" - android:textAppearance="?android:attr/textAppearanceSmall" - android:text="@string/color_picker_button_more" /> - </FrameLayout> - - </RelativeLayout> -</ScrollView>
\ No newline at end of file diff --git a/chromium/ui/android/java/res/layout/color_picker_dialog_title.xml b/chromium/ui/android/java/res/layout/color_picker_dialog_title.xml deleted file mode 100644 index d97cafb9197..00000000000 --- a/chromium/ui/android/java/res/layout/color_picker_dialog_title.xml +++ /dev/null @@ -1,41 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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. ---> - -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingBottom="15dp" - android:paddingStart="20dp" - android:paddingEnd="20dp" - android:paddingTop="15dp" > - - <TextView - android:id="@+id/title" - style="?android:attr/textAppearanceLarge" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_toStartOf="@+id/selected_color_view_border" - android:layout_centerVertical="true" - android:textColor="#33B5E5" - android:ellipsize="end" - android:singleLine="true" /> - - <FrameLayout - android:layout_width="40dp" - android:layout_height="40dp" - android:layout_alignParentEnd="true" - android:id="@+id/selected_color_view_border" - android:background="@drawable/color_picker_border" - android:padding="2px"> - - <View - android:id="@+id/selected_color_view" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:background="@android:color/black" /> - </FrameLayout> - -</RelativeLayout>
\ No newline at end of file diff --git a/chromium/ui/android/java/res/values-v17/styles.xml b/chromium/ui/android/java/res/values-v17/styles.xml deleted file mode 100644 index 8295ddf644d..00000000000 --- a/chromium/ui/android/java/res/values-v17/styles.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<!-- 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. ---> - -<resources> - <style name="AutofillPopupWindow" parent="@android:style/Widget.ListPopupWindow"> - <item name="android:popupBackground">@drawable/autofill_popup_background</item> - </style> -</resources>
\ No newline at end of file diff --git a/chromium/ui/android/java/res/values/colors.xml b/chromium/ui/android/java/res/values/colors.xml deleted file mode 100644 index be5896dac2d..00000000000 --- a/chromium/ui/android/java/res/values/colors.xml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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. ---> -<resources> - <color name="color_picker_border_color">#B0B0B0</color> -</resources> - diff --git a/chromium/ui/android/java/res/values/dimens.xml b/chromium/ui/android/java/res/values/dimens.xml deleted file mode 100644 index ed863728627..00000000000 --- a/chromium/ui/android/java/res/values/dimens.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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. ---> -<resources> - - <!-- - 14.5 = Seekbar thumb width - border width, but it depends on the width - of the seek bar icon. - --> - <dimen name="color_picker_gradient_margin">14.5dp</dimen> - -</resources>
\ No newline at end of file diff --git a/chromium/ui/android/java/res/values/strings.xml b/chromium/ui/android/java/res/values/strings.xml deleted file mode 100644 index 850bcc5c5e6..00000000000 --- a/chromium/ui/android/java/res/values/strings.xml +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (c) 2012 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. ---> - -<!-- DO NOT ADD STRINGS HERE. - - Android ui strings now live in - ui/android/java/strings/android_ui_strings.grd - - See http://www.chromium.org/developers/design-documents/ui-localization ---> - -<resources/> diff --git a/chromium/ui/android/java/res/values/values.xml b/chromium/ui/android/java/res/values/values.xml deleted file mode 100644 index 046cf8b15e1..00000000000 --- a/chromium/ui/android/java/res/values/values.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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. ---> - -<resources xmlns:android="http://schemas.android.com/apk/res/android"> - <!-- AutofillPopup constants --> - <item type="id" name="autofill_popup_window" /> -</resources>
\ No newline at end of file diff --git a/chromium/ui/android/java/resource_map/OWNERS b/chromium/ui/android/java/resource_map/OWNERS deleted file mode 100644 index d85278d5ee5..00000000000 --- a/chromium/ui/android/java/resource_map/OWNERS +++ /dev/null @@ -1,13 +0,0 @@ -# Changes in this folder are guaranteed to affect the downstream -# android_webview build. Adding one of the folks from the below list to the -# review gives us time to prepare a matching change ahead of time so that our -# downstream build can continue running smoothly. -set noparent - -benm@chromium.org -boliu@chomium.org -joth@chromium.org -mkosiba@chromium.org -mnaganov@chromium.org -primiano@chromium.org -torne@chromium.org diff --git a/chromium/ui/android/java/resource_map/org/chromium/ui/R.java b/chromium/ui/android/java/resource_map/org/chromium/ui/R.java deleted file mode 100644 index c722c145b2b..00000000000 --- a/chromium/ui/android/java/resource_map/org/chromium/ui/R.java +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2012 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. - -package org.chromium.ui; - -/** - * Provide Android internal resources to Chrome's ui layer. This allows classes - * that access resources via org.chromium.ui.R to function properly in webview. - * In a normal Chrome build, ui resources live in a res folder in the ui layer - * and the org.chromium.ui.R class is generated at build time based on these - * resources. In webview, resources live in the Android framework and can't be - * accessed directly from the ui layer. Instead, we copy resources needed by ui - * into the Android framework and use this R class to map resources IDs from - * org.chromium.ui.R to com.android.internal.R. - */ -public final class R { - public static final class string { - public static int low_memory_error; - public static int opening_file_error; - public static int color_picker_button_more; - public static int color_picker_hue; - public static int color_picker_saturation; - public static int color_picker_value; - public static int color_picker_button_set; - public static int color_picker_button_cancel; - public static int color_picker_dialog_title; - } - public static final class id { - public static int autofill_label; - public static int autofill_popup_window; - public static int autofill_sublabel; - public static int selected_color_view; - public static int title; - public static int more_colors_button; - public static int color_picker_advanced; - public static int color_picker_simple; - public static int more_colors_button_border; - public static int color_picker_simple_border; - public static int gradient; - public static int text; - public static int seek_bar; - } - public static final class layout { - public static int autofill_text; - public static int color_picker_dialog_title; - public static int color_picker_dialog_content; - public static int color_picker_advanced_component; - } - public static final class drawable { - public static int color_picker_advanced_select_handle; - } - public static final class style { - public static int AutofillPopupWindow; - } - public static final class color { - public static int color_picker_border_color; - } -} diff --git a/chromium/ui/android/java/src/org/chromium/ui/Clipboard.java b/chromium/ui/android/java/src/org/chromium/ui/Clipboard.java deleted file mode 100644 index a66fa3d91dd..00000000000 --- a/chromium/ui/android/java/src/org/chromium/ui/Clipboard.java +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) 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. - -package org.chromium.ui; - -import org.chromium.base.CalledByNative; -import org.chromium.base.JNINamespace; - -import android.content.ClipData; -import android.content.ClipboardManager; -import android.content.Context; -import android.text.TextUtils; - -/** - * Simple proxy that provides C++ code with an access pathway to the Android - * clipboard. - */ -@JNINamespace("ui") -public class Clipboard { - // Necessary for coercing clipboard contents to text if they require - // access to network resources, etceteras (e.g., URI in clipboard) - private final Context mContext; - - private final ClipboardManager mClipboardManager; - - /** - * Use the factory constructor instead. - * - * @param context for accessing the clipboard - */ - private Clipboard(final Context context) { - mContext = context; - mClipboardManager = (ClipboardManager) - context.getSystemService(Context.CLIPBOARD_SERVICE); - } - - /** - * Returns a new Clipboard object bound to the specified context. - * - * @param context for accessing the clipboard - * @return the new object - */ - @CalledByNative - private static Clipboard create(final Context context) { - return new Clipboard(context); - } - - /** - * Emulates the behavior of the now-deprecated - * {@link android.text.ClipboardManager#getText()} by invoking - * {@link android.content.ClipData.Item#coerceToText(Context)} on the first - * item in the clipboard (if any) and returning the result as a string. - * <p> - * This is quite different than simply calling {@link Object#toString()} on - * the clip; consumers of this API should familiarize themselves with the - * process described in - * {@link android.content.ClipData.Item#coerceToText(Context)} before using - * this method. - * - * @return a string representation of the first item on the clipboard, if - * the clipboard currently has an item and coercion of the item into - * a string is possible; otherwise, <code>null</code> - */ - @SuppressWarnings("javadoc") - @CalledByNative - private String getCoercedText() { - final ClipData clip = mClipboardManager.getPrimaryClip(); - if (clip != null && clip.getItemCount() > 0) { - final CharSequence sequence = clip.getItemAt(0).coerceToText(mContext); - if (sequence != null) { - return sequence.toString(); - } - } - return null; - } - - /** - * Emulates the behavior of the now-deprecated - * {@link android.text.ClipboardManager#setText(CharSequence)}, setting the - * clipboard's current primary clip to a plain-text clip that consists of - * the specified string. - * - * @param text will become the content of the clipboard's primary clip - */ - @SuppressWarnings("javadoc") - @CalledByNative - private void setText(final String text) { - mClipboardManager.setPrimaryClip(ClipData.newPlainText(null, text)); - } - - /** - * Approximates the behavior of the now-deprecated - * {@link android.text.ClipboardManager#hasText()}, returning true if and - * only if the clipboard has a primary clip and that clip contains a plain - * non-empty text entry (without attempting coercion - URLs and intents - * will cause this method to return false). - * - * @return as described above - */ - @SuppressWarnings("javadoc") - @CalledByNative - private boolean hasPlainText() { - final ClipData clip = mClipboardManager.getPrimaryClip(); - if (clip != null && clip.getItemCount() > 0) { - final CharSequence text = clip.getItemAt(0).getText(); - return !TextUtils.isEmpty(text); - } - return false; - } -} diff --git a/chromium/ui/android/java/src/org/chromium/ui/ColorPickerAdvanced.java b/chromium/ui/android/java/src/org/chromium/ui/ColorPickerAdvanced.java deleted file mode 100644 index 91800eaa8f6..00000000000 --- a/chromium/ui/android/java/src/org/chromium/ui/ColorPickerAdvanced.java +++ /dev/null @@ -1,252 +0,0 @@ -// 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. - -package org.chromium.ui; - -import android.content.Context; -import android.graphics.Color; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.view.accessibility.AccessibilityEvent; -import android.widget.LinearLayout; -import android.widget.SeekBar; -import android.widget.SeekBar.OnSeekBarChangeListener; - -/** - * Represents a more advanced way for the user to choose a color, based on selecting each of - * the Hue, Saturation and Value attributes. - */ -public class ColorPickerAdvanced extends LinearLayout implements OnSeekBarChangeListener { - private static final int HUE_SEEK_BAR_MAX = 360; - - private static final int HUE_COLOR_COUNT = 7; - - private static final int SATURATION_SEEK_BAR_MAX = 100; - - private static final int SATURATION_COLOR_COUNT = 2; - - private static final int VALUE_SEEK_BAR_MAX = 100; - - private static final int VALUE_COLOR_COUNT = 2; - - ColorPickerAdvancedComponent mHueDetails; - - ColorPickerAdvancedComponent mSaturationDetails; - - ColorPickerAdvancedComponent mValueDetails; - - private OnColorChangedListener mOnColorChangedListener; - - private int mCurrentColor; - - private final float[] mCurrentHsvValues = new float[3]; - - public ColorPickerAdvanced(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - public ColorPickerAdvanced(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - init(); - } - - public ColorPickerAdvanced(Context context) { - super(context); - init(); - } - - /** - * Initializes all the views and variables in the advanced view. - */ - private void init() { - setOrientation(LinearLayout.VERTICAL); - - mHueDetails = createAndAddNewGradient(R.string.color_picker_hue, - HUE_SEEK_BAR_MAX, this); - mSaturationDetails = createAndAddNewGradient(R.string.color_picker_saturation, - SATURATION_SEEK_BAR_MAX, this); - mValueDetails = createAndAddNewGradient(R.string.color_picker_value, - VALUE_SEEK_BAR_MAX, this); - - refreshGradientComponents(); - } - - /** - * Creates a new GradientDetails object from the parameters provided, initializes it, - * and adds it to this advanced view. - * - * @param textResourceId The text to display for the label. - * @param seekBarMax The maximum value of the seek bar for the gradient. - * @param seekBarListener Object listening to when the user changes the seek bar. - * - * @return A new GradientDetails object initialized with the given parameters. - */ - public ColorPickerAdvancedComponent createAndAddNewGradient(int textResourceId, - int seekBarMax, - OnSeekBarChangeListener seekBarListener) { - LayoutInflater inflater = (LayoutInflater) getContext() - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - View newComponent = inflater.inflate(R.layout.color_picker_advanced_component, null); - addView(newComponent); - - return new ColorPickerAdvancedComponent(newComponent, - textResourceId, - seekBarMax, - seekBarListener); - } - - /** - * Sets the listener for when the user changes the color. - * - * @param onColorChangedListener The object listening for the change in color. - */ - public void setListener(OnColorChangedListener onColorChangedListener) { - mOnColorChangedListener = onColorChangedListener; - } - - /** - * @return The color the user has currently chosen. - */ - public int getColor() { - return mCurrentColor; - } - - /** - * Sets the color that the user has currently chosen. - * - * @param color The currently chosen color. - */ - public void setColor(int color) { - mCurrentColor = color; - Color.colorToHSV(mCurrentColor, mCurrentHsvValues); - refreshGradientComponents(); - } - - /** - * Notifies the listener, if there is one, of a change in the selected color. - */ - private void notifyColorChanged() { - if (mOnColorChangedListener != null) { - mOnColorChangedListener.onColorChanged(getColor()); - } - } - - /** - * Callback for when a slider is updated on the advanced view. - * - * @param seekBar The color slider that was updated. - * @param progress The new value of the color slider. - * @param fromUser Whether it was the user the changed the value, or whether - * we were setting it up. - */ - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - if (fromUser) { - mCurrentHsvValues[0] = mHueDetails.getValue(); - mCurrentHsvValues[1] = mSaturationDetails.getValue() / 100.0f; - mCurrentHsvValues[2] = mValueDetails.getValue() / 100.0f; - - mCurrentColor = Color.HSVToColor(mCurrentHsvValues); - - updateHueGradient(); - updateSaturationGradient(); - updateValueGradient(); - - notifyColorChanged(); - } - } - - /** - * Updates only the hue gradient display with the hue value for the - * currently selected color. - */ - private void updateHueGradient() { - float[] tempHsvValues = new float[3]; - tempHsvValues[1] = mCurrentHsvValues[1]; - tempHsvValues[2] = mCurrentHsvValues[2]; - - int[] newColors = new int[HUE_COLOR_COUNT]; - - for (int i = 0; i < HUE_COLOR_COUNT; ++i) { - tempHsvValues[0] = i * 60.0f; - newColors[i] = Color.HSVToColor(tempHsvValues); - } - mHueDetails.setGradientColors(newColors); - } - - /** - * Updates only the saturation gradient display with the saturation value - * for the currently selected color. - */ - private void updateSaturationGradient() { - float[] tempHsvValues = new float[3]; - tempHsvValues[0] = mCurrentHsvValues[0]; - tempHsvValues[1] = 0.0f; - tempHsvValues[2] = mCurrentHsvValues[2]; - - int[] newColors = new int[SATURATION_COLOR_COUNT]; - - newColors[0] = Color.HSVToColor(tempHsvValues); - - tempHsvValues[1] = 1.0f; - newColors[1] = Color.HSVToColor(tempHsvValues); - mSaturationDetails.setGradientColors(newColors); - } - - /** - * Updates only the Value gradient display with the Value amount for - * the currently selected color. - */ - private void updateValueGradient() { - float[] tempHsvValues = new float[3]; - tempHsvValues[0] = mCurrentHsvValues[0]; - tempHsvValues[1] = mCurrentHsvValues[1]; - tempHsvValues[2] = 0.0f; - - int[] newColors = new int[VALUE_COLOR_COUNT]; - - newColors[0] = Color.HSVToColor(tempHsvValues); - - tempHsvValues[2] = 1.0f; - newColors[1] = Color.HSVToColor(tempHsvValues); - mValueDetails.setGradientColors(newColors); - } - - /** - * Updates all the gradient displays to show the currently selected color. - */ - private void refreshGradientComponents() { - // Round and bound the saturation value. - int saturationValue = Math.round(mCurrentHsvValues[1] * 100.0f); - saturationValue = Math.min(saturationValue, SATURATION_SEEK_BAR_MAX); - saturationValue = Math.max(saturationValue, 0); - - // Round and bound the Value amount. - int valueValue = Math.round(mCurrentHsvValues[2] * 100.0f); - valueValue = Math.min(valueValue, VALUE_SEEK_BAR_MAX); - valueValue = Math.max(valueValue, 0); - - // Don't need to round the hue value since its possible values match the seek bar - // range directly. - mHueDetails.setValue(mCurrentHsvValues[0]); - mSaturationDetails.setValue(saturationValue); - mValueDetails.setValue(valueValue); - - updateHueGradient(); - updateSaturationGradient(); - updateValueGradient(); - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // Do nothing. - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // Do nothing. - } -} diff --git a/chromium/ui/android/java/src/org/chromium/ui/ColorPickerAdvancedComponent.java b/chromium/ui/android/java/src/org/chromium/ui/ColorPickerAdvancedComponent.java deleted file mode 100644 index 1e679d5fe8f..00000000000 --- a/chromium/ui/android/java/src/org/chromium/ui/ColorPickerAdvancedComponent.java +++ /dev/null @@ -1,94 +0,0 @@ -// 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. - -package org.chromium.ui; - -import android.content.Context; -import android.graphics.drawable.GradientDrawable; -import android.graphics.drawable.GradientDrawable.Orientation; -import android.os.Build; -import android.view.View; -import android.widget.SeekBar; -import android.widget.SeekBar.OnSeekBarChangeListener; -import android.widget.TextView; -import org.chromium.base.ApiCompatibilityUtils; - -/** - * Encapsulates a single gradient view of the HSV color display, including its label, gradient - * view and seek bar. - * - * Mirrors a "color_picker_advanced_component" layout. - */ -public class ColorPickerAdvancedComponent { - // The view that displays the gradient. - private final View mGradientView; - // The seek bar that allows the user to change the value of this component. - private final SeekBar mSeekBar; - // The set of colors to interpolate the gradient through. - private int[] mGradientColors; - // The Drawable that represents the gradient. - private GradientDrawable mGradientDrawable; - // The text label for the component. - private final TextView mText; - - /** - * Initializes the views. - * - * @param rootView View that contains all the content, such as the label, gradient view, etc. - * @param textResourceId The resource ID of the text to show on the label. - * @param seekBarMax The range of the seek bar. - * @param seekBarListener The listener for when the seek bar value changes. - */ - ColorPickerAdvancedComponent(final View rootView, - final int textResourceId, - final int seekBarMax, - final OnSeekBarChangeListener seekBarListener) { - mGradientView = rootView.findViewById(R.id.gradient); - mText = (TextView) rootView.findViewById(R.id.text); - mText.setText(textResourceId); - mGradientDrawable = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, null); - mSeekBar = (SeekBar) rootView.findViewById(R.id.seek_bar); - mSeekBar.setOnSeekBarChangeListener(seekBarListener); - mSeekBar.setMax(seekBarMax); - // Setting the thumb offset means the seek bar thumb can move all the way to each end - // of the gradient view. - Context context = rootView.getContext(); - int offset = context.getResources() - .getDrawable(R.drawable.color_picker_advanced_select_handle) - .getIntrinsicWidth(); - mSeekBar.setThumbOffset(offset / 2); - } - - /** - * @return The value represented by this component, maintained by the seek bar progress. - */ - public float getValue() { - return mSeekBar.getProgress(); - } - - /** - * Sets the value of the component (by setting the seek bar value). - * - * @param newValue The value to give the component. - */ - public void setValue(float newValue) { - mSeekBar.setProgress((int) newValue); - } - - /** - * Sets the colors for the gradient view to interpolate through. - * - * @param newColors The set of colors representing the interpolation points for the gradient. - */ - public void setGradientColors(int[] newColors) { - mGradientColors = newColors.clone(); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { - Orientation currentOrientation = Orientation.LEFT_RIGHT; - mGradientDrawable = new GradientDrawable(currentOrientation, mGradientColors); - } else { - mGradientDrawable.setColors(mGradientColors); - } - ApiCompatibilityUtils.setBackgroundForView(mGradientView, mGradientDrawable); - } -} diff --git a/chromium/ui/android/java/src/org/chromium/ui/ColorPickerDialog.java b/chromium/ui/android/java/src/org/chromium/ui/ColorPickerDialog.java deleted file mode 100644 index 58f1e0a3023..00000000000 --- a/chromium/ui/android/java/src/org/chromium/ui/ColorPickerDialog.java +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright (c) 2012 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. - -package org.chromium.ui; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.content.Context; -import android.content.DialogInterface; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.Button; -import android.widget.TextView; - -/** - * UI for the color chooser that shows on the Android platform as a result of - * <input type=color > form element. - */ -public class ColorPickerDialog extends AlertDialog implements OnColorChangedListener { - private final ColorPickerAdvanced mAdvancedColorPicker; - - private final ColorPickerSimple mSimpleColorPicker; - - private final Button mMoreButton; - - // The view up in the corner that shows the user the color they've currently selected. - private final View mCurrentColorView; - - private final OnColorChangedListener mListener; - - private final int mInitialColor; - - private int mCurrentColor; - - /** - * @param context The context the dialog is to run in. - * @param theme The theme to display the dialog in. - * @param listener The object to notify when the color is set. - * @param color The initial color to set. - */ - public ColorPickerDialog(Context context, OnColorChangedListener listener, int color) { - super(context, 0); - - mListener = listener; - mInitialColor = color; - mCurrentColor = mInitialColor; - - // Initialize title - LayoutInflater inflater = (LayoutInflater) context - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - View title = inflater.inflate(R.layout.color_picker_dialog_title, null); - setCustomTitle(title); - - mCurrentColorView = title.findViewById(R.id.selected_color_view); - - TextView titleText = (TextView) title.findViewById(R.id.title); - titleText.setText(R.string.color_picker_dialog_title); - - // Initialize Set/Cancel buttons - String positiveButtonText = context.getString(R.string.color_picker_button_set); - setButton(BUTTON_POSITIVE, positiveButtonText, - new Dialog.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - tryNotifyColorSet(mCurrentColor); - } - }); - - // Note that with the color picker there's not really any such thing as - // "cancelled". - // The color picker flow only finishes when we return a color, so we - // have to always - // return something. The concept of "cancelled" in this case just means - // returning - // the color that we were initialized with. - String negativeButtonText = context.getString(R.string.color_picker_button_cancel); - setButton(BUTTON_NEGATIVE, negativeButtonText, - new Dialog.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - tryNotifyColorSet(mInitialColor); - } - }); - - setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface arg0) { - tryNotifyColorSet(mInitialColor); - } - }); - - // Initialize main content view - View content = inflater.inflate(R.layout.color_picker_dialog_content, null); - setView(content); - - // Initialize More button. - mMoreButton = (Button) content.findViewById(R.id.more_colors_button); - mMoreButton.setOnClickListener(new Button.OnClickListener() { - @Override - public void onClick(View v) { - showAdvancedView(); - } - }); - - // Initialize advanced color view (hidden initially). - mAdvancedColorPicker = - (ColorPickerAdvanced) content.findViewById(R.id.color_picker_advanced); - mAdvancedColorPicker.setVisibility(View.GONE); - - // Initialize simple color view (default view). - mSimpleColorPicker = (ColorPickerSimple) content.findViewById(R.id.color_picker_simple); - mSimpleColorPicker.init(this); - - updateCurrentColor(mInitialColor); - } - - /** - * Listens to the ColorPicker for when the user has changed the selected color, and - * updates the current color (the color shown in the title) accordingly. - * - * @param color The new color chosen by the user. - */ - @Override - public void onColorChanged(int color) { - updateCurrentColor(color); - } - - /** - * Hides the simple view (the default) and shows the advanced one instead, hiding the - * "More" button at the same time. - */ - private void showAdvancedView() { - // Only need to hide the borders, not the Views themselves, since the Views are - // contained within the borders. - View buttonBorder = findViewById(R.id.more_colors_button_border); - buttonBorder.setVisibility(View.GONE); - - View simpleViewBorder = findViewById(R.id.color_picker_simple_border); - simpleViewBorder.setVisibility(View.GONE); - - mAdvancedColorPicker.setVisibility(View.VISIBLE); - mAdvancedColorPicker.setListener(this); - mAdvancedColorPicker.setColor(mCurrentColor); - } - - /** - * Tries to notify any listeners that the color has been set. - */ - private void tryNotifyColorSet(int color) { - if (mListener != null) { - mListener.onColorChanged(color); - } - } - - /** - * Updates the internal cache of the currently selected color, updating the colorful little - * box in the title at the same time. - */ - private void updateCurrentColor(int color) { - mCurrentColor = color; - if (mCurrentColorView != null) { - mCurrentColorView.setBackgroundColor(color); - } - } -} diff --git a/chromium/ui/android/java/src/org/chromium/ui/ColorPickerMoreButton.java b/chromium/ui/android/java/src/org/chromium/ui/ColorPickerMoreButton.java deleted file mode 100644 index a982afd9e54..00000000000 --- a/chromium/ui/android/java/src/org/chromium/ui/ColorPickerMoreButton.java +++ /dev/null @@ -1,56 +0,0 @@ -// 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. - -package org.chromium.ui; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Paint.Style; -import android.util.AttributeSet; -import android.widget.Button; - -/** - * Simple class that draws a white border around a button, purely for a UI change. - */ -public class ColorPickerMoreButton extends Button { - - // A cache for the paint used to draw the border, so it doesn't have to be created in - // every onDraw() call. - private Paint mBorderPaint; - - public ColorPickerMoreButton(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - public ColorPickerMoreButton(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - init(); - } - - /** - * Sets up the paint to use for drawing the border. - */ - public void init() { - mBorderPaint = new Paint(); - mBorderPaint.setStyle(Paint.Style.STROKE); - mBorderPaint.setColor(Color.WHITE); - // Set the width to one pixel. - mBorderPaint.setStrokeWidth(1.0f); - // And make sure the border doesn't bleed into the outside. - mBorderPaint.setAntiAlias(false); - } - - /** - * Draws the border around the edge of the button. - * - * @param canvas The canvas to draw on. - */ - @Override - protected void onDraw(Canvas canvas) { - canvas.drawRect(0.5f, 0.5f, getWidth() - 1.5f, getHeight() - 1.5f, mBorderPaint); - super.onDraw(canvas); - } -} diff --git a/chromium/ui/android/java/src/org/chromium/ui/ColorPickerSimple.java b/chromium/ui/android/java/src/org/chromium/ui/ColorPickerSimple.java deleted file mode 100644 index 979405a4078..00000000000 --- a/chromium/ui/android/java/src/org/chromium/ui/ColorPickerSimple.java +++ /dev/null @@ -1,189 +0,0 @@ -// 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. -package org.chromium.ui; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Rect; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; - - -/** - * Draws a grid of (predefined) colors and allows the user to choose one of - * those colors. - */ -public class ColorPickerSimple extends View { - private static final int ROW_COUNT = 2; - - private static final int COLUMN_COUNT = 4; - - private static final int GRID_CELL_COUNT = ROW_COUNT * COLUMN_COUNT; - - private static final int[] COLORS = { Color.RED, - Color.CYAN, - Color.BLUE, - Color.GREEN, - Color.MAGENTA, - Color.YELLOW, - Color.BLACK, - Color.WHITE - }; - - private Paint mBorderPaint; - - private Rect[] mBounds; - - private Paint[] mPaints; - - private OnColorChangedListener mOnColorTouchedListener; - - private int mLastTouchedXPosition; - - private int mLastTouchedYPosition; - - public ColorPickerSimple(Context context) { - super(context); - } - - public ColorPickerSimple(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public ColorPickerSimple(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - /** - * Initializes the listener and precalculates the grid and color positions. - * - * @param onColorChangedListener The listener that gets notified when the user touches - * a color. - */ - public void init(OnColorChangedListener onColorChangedListener) { - mOnColorTouchedListener = onColorChangedListener; - - // This will get calculated when the layout size is updated. - mBounds = null; - - mPaints = new Paint[GRID_CELL_COUNT]; - for (int i = 0; i < GRID_CELL_COUNT; ++i) { - Paint newPaint = new Paint(); - newPaint.setColor(COLORS[i]); - mPaints[i] = newPaint; - } - - mBorderPaint = new Paint(); - int borderColor = getContext().getResources().getColor(R.color.color_picker_border_color); - mBorderPaint.setColor(borderColor); - - // Responds to the user touching the grid and works out which color has been chosen as - // a result, depending on the X,Y coordinate. Note that we respond to the click event - // here, but the onClick() method doesn't provide us with the X,Y coordinates, so we - // track them in onTouchEvent() below. This way the grid reacts properly to touch events - // whereas if we put this onClick() code in onTouchEvent below then we get some strange - // interactions with the ScrollView in the parent ColorPickerDialog. - setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (mOnColorTouchedListener != null && getWidth() > 0 && getHeight() > 0) { - int column = mLastTouchedXPosition * COLUMN_COUNT / getWidth(); - int row = mLastTouchedYPosition * ROW_COUNT / getHeight(); - - int colorIndex = (row * COLUMN_COUNT) + column; - if (colorIndex >= 0 && colorIndex < COLORS.length) { - mOnColorTouchedListener.onColorChanged(COLORS[colorIndex]); - } - } - } - }); - } - - /** - * Draws the grid of colors, based on the rectangles calculated in onSizeChanged(). - * Also draws borders in between the colored rectangles. - * - * @param canvas The canvas the colors are drawn onto. - */ - @Override - public void onDraw(Canvas canvas) { - if (mBounds == null || mPaints == null) { - return; - } - - canvas.drawColor(Color.WHITE); - - // Draw the actual colored rectangles. - for (int i = 0; i < GRID_CELL_COUNT; ++i) { - canvas.drawRect(mBounds[i], mPaints[i]); - } - - // Draw 1px borders between the rows. - for (int i = 0; i < ROW_COUNT - 1; ++i) { - canvas.drawLine(0, - mBounds[i * COLUMN_COUNT].bottom + 1, - getWidth(), - mBounds[i * COLUMN_COUNT].bottom + 1, - mBorderPaint); - } - - // Draw 1px borders between the columns. - for (int j = 0; j < COLUMN_COUNT - 1; ++j) { - canvas.drawLine(mBounds[j].right + 1, - 0, - mBounds[j].right + 1, - getHeight(), - mBorderPaint); - } - } - - /** - * Stores the X,Y coordinates of the touch so that we can use them in the onClick() listener - * above to work out where the click was on the grid. - * - * @param event The MotionEvent the X,Y coordinates are retrieved from. - */ - @Override - public boolean onTouchEvent(MotionEvent event) { - if (event.getAction() == MotionEvent.ACTION_DOWN) { - mLastTouchedXPosition = (int) event.getX(); - mLastTouchedYPosition = (int) event.getY(); - } - return super.onTouchEvent(event); - } - - /** - * Recalculates the color grid with the new sizes. - */ - @Override - protected void onSizeChanged(int width, int height, int oldw, int oldh) { - calculateGrid(width, height); - } - - /** - * Calculates the sizes and positions of the cells in the grid, splitting - * them up as evenly as possible. Leaves 3 pixels between each cell so that - * we can draw a border between them as well, and leaves a pixel around the - * edge. - */ - private void calculateGrid(final int width, final int height) { - mBounds = new Rect[GRID_CELL_COUNT]; - - for (int i = 0; i < ROW_COUNT; ++i) { - for (int j = 0; j < COLUMN_COUNT; ++j) { - int left = j * (width + 1) / COLUMN_COUNT + 1; - int right = (j + 1) * (width + 1) / COLUMN_COUNT - 2; - - int top = i * (height + 1) / ROW_COUNT + 1; - int bottom = (i + 1) * (height + 1) / ROW_COUNT - 2; - - Rect rect = new Rect(left, top, right, bottom); - mBounds[(i * COLUMN_COUNT) + j] = rect; - } - } - } -} diff --git a/chromium/ui/android/java/src/org/chromium/ui/LocalizationUtils.java b/chromium/ui/android/java/src/org/chromium/ui/LocalizationUtils.java deleted file mode 100644 index f421d8939f1..00000000000 --- a/chromium/ui/android/java/src/org/chromium/ui/LocalizationUtils.java +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) 2012 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. - -package org.chromium.ui; - -import org.chromium.base.CalledByNative; -import org.chromium.base.JNINamespace; - -import android.os.Build; -import android.text.TextUtils; -import android.view.View; - -import java.util.Locale; - -/** - * This class provides the locale related methods for the native library. - */ -@JNINamespace("l10n_util") -public class LocalizationUtils { - - // This is mirrored from base/i18n/rtl.h. Please keep in sync. - public static final int UNKNOWN_DIRECTION = 0; - public static final int RIGHT_TO_LEFT = 1; - public static final int LEFT_TO_RIGHT = 2; - - private LocalizationUtils() { /* cannot be instantiated */ } - - /** - * @return the default locale, translating Android deprecated - * language codes into the modern ones used by Chromium. - */ - @CalledByNative - public static String getDefaultLocale() { - Locale locale = Locale.getDefault(); - String language = locale.getLanguage(); - String country = locale.getCountry(); - - // Android uses deprecated lanuages codes for Hebrew and Indonesian but Chromium uses the - // updated codes. Also, Android uses "tl" while Chromium uses "fil" for Tagalog/Filipino. - // So apply a mapping. - // See http://developer.android.com/reference/java/util/Locale.html - if ("iw".equals(language)) { - language = "he"; - } else if ("in".equals(language)) { - language = "id"; - } else if ("tl".equals(language)) { - language = "fil"; - } - return country.isEmpty() ? language : language + "-" + country; - } - - @CalledByNative - private static Locale getJavaLocale(String language, String country, String variant) { - return new Locale(language, country, variant); - } - - @CalledByNative - private static String getDisplayNameForLocale(Locale locale, Locale displayLocale) { - return locale.getDisplayName(displayLocale); - } - - /** - * @return true if the system default layout direction is RTL, false otherwise. - * RTL layout support is from Jelly Bean MR1, so if the version is lower - * than that, it is always false. - */ - public static boolean isSystemLayoutDirectionRtl() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - return TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) - == View.LAYOUT_DIRECTION_RTL; - } - return false; - } - - /** - * Jni binding to base::i18n::IsRTL. - * @return true if the current locale is right to left. - */ - public static boolean isRtl() { - return nativeIsRTL(); - } - - /** - * Jni binding to base::i18n::GetFirstStrongCharacterDirection - * @param string String to decide the direction. - * @return One of the UNKNOWN_DIRECTION, RIGHT_TO_LEFT, and LEFT_TO_RIGHT. - */ - public static int getFirstStrongCharacterDirection(String string) { - return nativeGetFirstStrongCharacterDirection(string); - } - - private static native boolean nativeIsRTL(); - - private static native int nativeGetFirstStrongCharacterDirection(String string); -} diff --git a/chromium/ui/android/java/src/org/chromium/ui/OnColorChangedListener.java b/chromium/ui/android/java/src/org/chromium/ui/OnColorChangedListener.java deleted file mode 100644 index 4caa3cf05bb..00000000000 --- a/chromium/ui/android/java/src/org/chromium/ui/OnColorChangedListener.java +++ /dev/null @@ -1,17 +0,0 @@ -// 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. -package org.chromium.ui; - -/** - * The callback used to indicate the user changed the color. - */ -public interface OnColorChangedListener { - - /** - * Called upon a color change. - * - * @param color The color that was set. - */ - void onColorChanged(int color); -}
\ No newline at end of file diff --git a/chromium/ui/android/java/src/org/chromium/ui/SelectFileDialog.java b/chromium/ui/android/java/src/org/chromium/ui/SelectFileDialog.java deleted file mode 100644 index 91533b52cf0..00000000000 --- a/chromium/ui/android/java/src/org/chromium/ui/SelectFileDialog.java +++ /dev/null @@ -1,248 +0,0 @@ -// Copyright (c) 2012 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. - -package org.chromium.ui; - -import android.app.Activity; -import android.content.ContentResolver; -import android.content.Intent; -import android.database.Cursor; -import android.net.Uri; -import android.os.Environment; -import android.provider.MediaStore; -import android.text.TextUtils; - -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.chromium.base.CalledByNative; -import org.chromium.base.JNINamespace; -import org.chromium.ui.WindowAndroid; - -/** - * A dialog that is triggered from a file input field that allows a user to select a file based on - * a set of accepted file types. The path of the selected file is passed to the native dialog. - */ -@JNINamespace("ui") -class SelectFileDialog implements WindowAndroid.IntentCallback{ - private static final String IMAGE_TYPE = "image/"; - private static final String VIDEO_TYPE = "video/"; - private static final String AUDIO_TYPE = "audio/"; - private static final String ALL_IMAGE_TYPES = IMAGE_TYPE + "*"; - private static final String ALL_VIDEO_TYPES = VIDEO_TYPE + "*"; - private static final String ALL_AUDIO_TYPES = AUDIO_TYPE + "*"; - private static final String ANY_TYPES = "*/*"; - private static final String CAPTURE_IMAGE_DIRECTORY = "browser-photos"; - - private final int mNativeSelectFileDialog; - private List<String> mFileTypes; - private boolean mCapture; - private Uri mCameraOutputUri; - - private SelectFileDialog(int nativeSelectFileDialog) { - mNativeSelectFileDialog = nativeSelectFileDialog; - } - - /** - * Creates and starts an intent based on the passed fileTypes and capture value. - * @param fileTypes MIME types requested (i.e. "image/*") - * @param capture The capture value as described in http://www.w3.org/TR/html-media-capture/ - * @param window The WindowAndroid that can show intents - */ - @CalledByNative - private void selectFile(String[] fileTypes, boolean capture, WindowAndroid window) { - mFileTypes = new ArrayList<String>(Arrays.asList(fileTypes)); - mCapture = capture; - - Intent chooser = new Intent(Intent.ACTION_CHOOSER); - Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); - mCameraOutputUri = Uri.fromFile(getFileForImageCapture()); - camera.putExtra(MediaStore.EXTRA_OUTPUT, mCameraOutputUri); - Intent camcorder = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); - Intent soundRecorder = new Intent( - MediaStore.Audio.Media.RECORD_SOUND_ACTION); - - // Quick check - if the |capture| parameter is set and |fileTypes| has the appropriate MIME - // type, we should just launch the appropriate intent. Otherwise build up a chooser based on - // the accept type and then display that to the user. - if (captureCamera()) { - if (window.showIntent(camera, this, R.string.low_memory_error)) return; - } else if (captureCamcorder()) { - if (window.showIntent(camcorder, this, R.string.low_memory_error)) return; - } else if (captureMicrophone()) { - if (window.showIntent(soundRecorder, this, R.string.low_memory_error)) return; - } - - Intent getContentIntent = new Intent(Intent.ACTION_GET_CONTENT); - getContentIntent.addCategory(Intent.CATEGORY_OPENABLE); - ArrayList<Intent> extraIntents = new ArrayList<Intent>(); - if (!noSpecificType()) { - // Create a chooser based on the accept type that was specified in the webpage. Note - // that if the web page specified multiple accept types, we will have built a generic - // chooser above. - if (shouldShowImageTypes()) { - extraIntents.add(camera); - getContentIntent.setType(ALL_IMAGE_TYPES); - } else if (shouldShowVideoTypes()) { - extraIntents.add(camcorder); - getContentIntent.setType(ALL_VIDEO_TYPES); - } else if (shouldShowAudioTypes()) { - extraIntents.add(soundRecorder); - getContentIntent.setType(ALL_AUDIO_TYPES); - } - } - - if (extraIntents.isEmpty()) { - // We couldn't resolve an accept type, so fallback to a generic chooser. - getContentIntent.setType(ANY_TYPES); - extraIntents.add(camera); - extraIntents.add(camcorder); - extraIntents.add(soundRecorder); - } - - chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, - extraIntents.toArray(new Intent[] { })); - - chooser.putExtra(Intent.EXTRA_INTENT, getContentIntent); - - if (!window.showIntent(chooser, this, R.string.low_memory_error)) { - onFileNotSelected(); - } - } - - /** - * Get a file for the image capture in the CAPTURE_IMAGE_DIRECTORY directory. - */ - private File getFileForImageCapture() { - File externalDataDir = Environment.getExternalStoragePublicDirectory( - Environment.DIRECTORY_DCIM); - File cameraDataDir = new File(externalDataDir.getAbsolutePath() + - File.separator + CAPTURE_IMAGE_DIRECTORY); - if (!cameraDataDir.exists() && !cameraDataDir.mkdirs()) { - cameraDataDir = externalDataDir; - } - File photoFile = new File(cameraDataDir.getAbsolutePath() + - File.separator + System.currentTimeMillis() + ".jpg"); - return photoFile; - } - - /** - * Callback method to handle the intent results and pass on the path to the native - * SelectFileDialog. - * @param window The window that has access to the application activity. - * @param resultCode The result code whether the intent returned successfully. - * @param contentResolver The content resolver used to extract the path of the selected file. - * @param results The results of the requested intent. - */ - @Override - public void onIntentCompleted(WindowAndroid window, int resultCode, - ContentResolver contentResolver, Intent results) { - if (resultCode != Activity.RESULT_OK) { - onFileNotSelected(); - return; - } - boolean success = false; - if (results == null) { - // If we have a successful return but no data, then assume this is the camera returning - // the photo that we requested. - nativeOnFileSelected(mNativeSelectFileDialog, mCameraOutputUri.getPath()); - success = true; - - // Broadcast to the media scanner that there's a new photo on the device so it will - // show up right away in the gallery (rather than waiting until the next time the media - // scanner runs). - window.sendBroadcast(new Intent( - Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, mCameraOutputUri)); - } else { - // We get back a content:// URI from the system if the user picked a file from the - // gallery. The ContentView has functionality that will convert that content:// URI to - // a file path on disk that Chromium understands. - Cursor c = contentResolver.query(results.getData(), - new String[] { MediaStore.MediaColumns.DATA }, null, null, null); - if (c != null) { - if (c.getCount() == 1) { - c.moveToFirst(); - String path = c.getString(0); - if (path != null) { - // Not all providers support the MediaStore.DATA column. For example, - // Gallery3D (com.android.gallery3d.provider) does not support it for - // Picasa Web Album images. - nativeOnFileSelected(mNativeSelectFileDialog, path); - success = true; - } - } - c.close(); - } - } - if (!success) { - onFileNotSelected(); - window.showError(R.string.opening_file_error); - } - } - - private void onFileNotSelected() { - nativeOnFileNotSelected(mNativeSelectFileDialog); - } - - private boolean noSpecificType() { - // We use a single Intent to decide the type of the file chooser we display to the user, - // which means we can only give it a single type. If there are multiple accept types - // specified, we will fallback to a generic chooser (unless a capture parameter has been - // specified, in which case we'll try to satisfy that first. - return mFileTypes.size() != 1 || mFileTypes.contains(ANY_TYPES); - } - - private boolean shouldShowTypes(String allTypes, String specificType) { - if (noSpecificType() || mFileTypes.contains(allTypes)) return true; - return acceptSpecificType(specificType); - } - - private boolean shouldShowImageTypes() { - return shouldShowTypes(ALL_IMAGE_TYPES,IMAGE_TYPE); - } - - private boolean shouldShowVideoTypes() { - return shouldShowTypes(ALL_VIDEO_TYPES, VIDEO_TYPE); - } - - private boolean shouldShowAudioTypes() { - return shouldShowTypes(ALL_AUDIO_TYPES, AUDIO_TYPE); - } - - private boolean acceptsSpecificType(String type) { - return mFileTypes.size() == 1 && TextUtils.equals(mFileTypes.get(0), type); - } - - private boolean captureCamera() { - return mCapture && acceptsSpecificType(ALL_IMAGE_TYPES); - } - - private boolean captureCamcorder() { - return mCapture && acceptsSpecificType(ALL_VIDEO_TYPES); - } - - private boolean captureMicrophone() { - return mCapture && acceptsSpecificType(ALL_AUDIO_TYPES); - } - - private boolean acceptSpecificType(String accept) { - for (String type : mFileTypes) { - if (type.startsWith(accept)) { - return true; - } - } - return false; - } - - @CalledByNative - private static SelectFileDialog create(int nativeSelectFileDialog) { - return new SelectFileDialog(nativeSelectFileDialog); - } - - private native void nativeOnFileSelected(int nativeSelectFileDialogImpl, - String filePath); - private native void nativeOnFileNotSelected(int nativeSelectFileDialogImpl); -} diff --git a/chromium/ui/android/java/src/org/chromium/ui/UiUtils.java b/chromium/ui/android/java/src/org/chromium/ui/UiUtils.java deleted file mode 100644 index 4a9fe15e79f..00000000000 --- a/chromium/ui/android/java/src/org/chromium/ui/UiUtils.java +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) 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. - -package org.chromium.ui; - -import android.content.Context; -import android.graphics.Rect; -import android.view.View; -import android.view.ViewGroup; -import android.view.inputmethod.InputMethodManager; - -/** - * Utility functions for common Android UI tasks. - * This class is not supposed to be instantiated. - */ -public class UiUtils { - /** - * Guards this class from being instantiated. - */ - private UiUtils() { - } - - /** The minimum size of the bottom margin below the app to detect a keyboard. */ - private static float KEYBOARD_DETECT_BOTTOM_THRESHOLD_DP = 100; - - /** - * Shows the software keyboard if necessary. - * @param view The currently focused {@link View}, which would receive soft keyboard input. - */ - public static void showKeyboard(View view) { - InputMethodManager imm = - (InputMethodManager) view.getContext().getSystemService( - Context.INPUT_METHOD_SERVICE); - // Only shows soft keyboard if there isn't an open physical keyboard. - imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); - } - - /** - * Hides the keyboard. - * @param view The {@link View} that is currently accepting input. - * @return Whether the keyboard was visible before. - */ - public static boolean hideKeyboard(View view) { - InputMethodManager imm = - (InputMethodManager) view.getContext().getSystemService( - Context.INPUT_METHOD_SERVICE); - return imm.hideSoftInputFromWindow(view.getWindowToken(), 0); - } - - public static boolean isKeyboardShowing(Context context, View view) { - View rootView = view.getRootView(); - if (rootView == null) return false; - Rect appRect = new Rect(); - rootView.getWindowVisibleDisplayFrame(appRect); - final float screenHeight = context.getResources().getDisplayMetrics().heightPixels; - final float bottomMargin = Math.abs(appRect.bottom - screenHeight); - final float density = context.getResources().getDisplayMetrics().density; - return bottomMargin > KEYBOARD_DETECT_BOTTOM_THRESHOLD_DP * density; - } - - /** - * Inserts a {@link View} into a {@link ViewGroup} after directly before a given {@View}. - * @param container The {@link View} to add newView to. - * @param newView The new {@link View} to add. - * @param existingView The {@link View} to insert the newView before. - * @return The index where newView was inserted, or -1 if it was not inserted. - */ - public static int insertBefore(ViewGroup container, View newView, View existingView) { - return insertView(container, newView, existingView, false); - } - - /** - * Inserts a {@link View} into a {@link ViewGroup} after directly after a given {@View}. - * @param container The {@link View} to add newView to. - * @param newView The new {@link View} to add. - * @param existingView The {@link View} to insert the newView after. - * @return The index where newView was inserted, or -1 if it was not inserted. - */ - public static int insertAfter(ViewGroup container, View newView, View existingView) { - return insertView(container, newView, existingView, true); - } - - private static int insertView( - ViewGroup container, View newView, View existingView, boolean after) { - // See if the view has already been added. - int index = container.indexOfChild(newView); - if (index >= 0) return index; - - // Find the location of the existing view. - index = container.indexOfChild(existingView); - if (index < 0) return -1; - - // Add the view. - if (after) index++; - container.addView(newView, index); - return index; - } -} diff --git a/chromium/ui/android/java/src/org/chromium/ui/ViewAndroid.java b/chromium/ui/android/java/src/org/chromium/ui/ViewAndroid.java deleted file mode 100644 index 97c8e1dcfd3..00000000000 --- a/chromium/ui/android/java/src/org/chromium/ui/ViewAndroid.java +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 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. - -package org.chromium.ui; - -import android.view.View; - -import org.chromium.base.JNINamespace; -import org.chromium.ui.ViewAndroidDelegate; -import org.chromium.ui.WindowAndroid; - -/** - * From the Chromium architecture point of view, ViewAndroid and its native counterpart - * serve purpose of representing Android view where Chrome expects to have a cross platform - * handle to the system view type. As Views are Java object on Android, this ViewAndroid - * and its native counterpart provide the expected abstractions on the C++ side and allow - * it to be flexibly glued to an actual Android Java View at runtime. - * - * It should only be used where access to Android Views is needed from the C++ code. - */ -@JNINamespace("ui") -public class ViewAndroid { - // Native pointer to the c++ ViewAndroid object. - private int mNativeViewAndroid = 0; - private final ViewAndroidDelegate mViewAndroidDelegate; - private final WindowAndroid mWindowAndroid; - private int mKeepScreenOnCount; - private View mKeepScreenOnView; - - /** - * Constructs a View object. - */ - public ViewAndroid(WindowAndroid nativeWindow, ViewAndroidDelegate viewAndroidDelegate) { - mWindowAndroid = nativeWindow; - mViewAndroidDelegate = viewAndroidDelegate; - mNativeViewAndroid = nativeInit(mWindowAndroid.getNativePointer()); - } - - public ViewAndroidDelegate getViewAndroidDelegate() { - return mViewAndroidDelegate; - } - - /** - * Destroys the c++ ViewAndroid object if one has been created. - */ - public void destroy() { - if (mNativeViewAndroid != 0) { - nativeDestroy(mNativeViewAndroid); - mNativeViewAndroid = 0; - } - } - - /** - * Returns a pointer to the c++ AndroidWindow object. - * @return A pointer to the c++ AndroidWindow. - */ - public int getNativePointer() { - return mNativeViewAndroid; - } - - /** - * Set KeepScreenOn flag. If the flag already set, increase mKeepScreenOnCount. - */ - public void incrementKeepScreenOnCount() { - mKeepScreenOnCount++; - if (mKeepScreenOnCount == 1) { - mKeepScreenOnView = mViewAndroidDelegate.acquireAnchorView(); - mKeepScreenOnView.setKeepScreenOn(true); - } - } - - /** - * Decrease mKeepScreenOnCount, if it is decreased to 0, remove the flag. - */ - public void decrementKeepScreenOnCount() { - assert mKeepScreenOnCount > 0; - mKeepScreenOnCount--; - if (mKeepScreenOnCount == 0) { - mViewAndroidDelegate.releaseAnchorView(mKeepScreenOnView); - mKeepScreenOnView = null; - } - } - - private native int nativeInit(int windowPtr); - private native void nativeDestroy(int nativeViewAndroid); -} diff --git a/chromium/ui/android/java/src/org/chromium/ui/ViewAndroidDelegate.java b/chromium/ui/android/java/src/org/chromium/ui/ViewAndroidDelegate.java deleted file mode 100644 index 531dce880a5..00000000000 --- a/chromium/ui/android/java/src/org/chromium/ui/ViewAndroidDelegate.java +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2012 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. - -package org.chromium.ui; - -import android.view.View; - -/** - * Interface to acquire and release anchor views from the implementing View. - */ -public interface ViewAndroidDelegate { - - /** - * @return An anchor view that can be used to anchor decoration views like Autofill popup. - */ - View acquireAnchorView(); - - /** - * Set the anchor view to specified position and width (all units in dp). - * @param view The anchor view that needs to be positioned. - * @param x X coordinate of the top left corner of the anchor view. - * @param y Y coordinate of the top left corner of the anchor view. - * @param width The width of the anchor view. - * @param height The height of the anchor view. - */ - void setAnchorViewPosition(View view, float x, float y, float width, float height); - - /** - * Release given anchor view. - * @param anchorView The anchor view that needs to be released. - */ - void releaseAnchorView(View anchorView); -}
\ No newline at end of file diff --git a/chromium/ui/android/java/src/org/chromium/ui/WindowAndroid.java b/chromium/ui/android/java/src/org/chromium/ui/WindowAndroid.java deleted file mode 100644 index 3fec6007b3c..00000000000 --- a/chromium/ui/android/java/src/org/chromium/ui/WindowAndroid.java +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright (c) 2012 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. - -package org.chromium.ui; - -import android.app.Activity; -import android.content.ActivityNotFoundException; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.util.SparseArray; -import android.widget.Toast; - -import java.util.HashMap; - -import org.chromium.base.JNINamespace; - -/** - * The window base class that has the minimum functionality. - */ -@JNINamespace("ui") -public class WindowAndroid { - - // Native pointer to the c++ WindowAndroid object. - private int mNativeWindowAndroid = 0; - - // Constants used for intent request code bounding. - private static final int REQUEST_CODE_PREFIX = 1000; - private static final int REQUEST_CODE_RANGE_SIZE = 100; - // A string used as a key to store intent errors in a bundle - static final String WINDOW_CALLBACK_ERRORS = "window_callback_errors"; - - private int mNextRequestCode = 0; - protected Activity mActivity; - protected SparseArray<IntentCallback> mOutstandingIntents; - protected HashMap<Integer, String> mIntentErrors; - - /** - * @param activity - */ - public WindowAndroid(Activity activity) { - mActivity = activity; - mOutstandingIntents = new SparseArray<IntentCallback>(); - mIntentErrors = new HashMap<Integer, String>(); - - } - - /** - * Shows an intent and returns the results to the callback object. - * @param intent The intent that needs to be showed. - * @param callback The object that will receive the results for the intent. - * @param errorId The ID of error string to be show if activity is paused before intent - * results. - * @return Whether the intent was shown. - */ - public boolean showIntent(Intent intent, IntentCallback callback, int errorId) { - int requestCode = REQUEST_CODE_PREFIX + mNextRequestCode; - mNextRequestCode = (mNextRequestCode + 1) % REQUEST_CODE_RANGE_SIZE; - - try { - mActivity.startActivityForResult(intent, requestCode); - } catch (ActivityNotFoundException e) { - return false; - } - - mOutstandingIntents.put(requestCode, callback); - mIntentErrors.put(requestCode, mActivity.getString(errorId)); - - return true; - } - - /** - * Displays an error message with a provided error message string. - * @param error The error message string to be displayed. - */ - public void showError(String error) { - if (error != null) { - Toast.makeText(mActivity, error, Toast.LENGTH_SHORT).show(); - } - } - - /** - * Displays an error message from the given resource id. - * @param resId The error message string's resource id. - */ - public void showError(int resId) { - showError(mActivity.getString(resId)); - } - - /** - * Displays an error message for a nonexistent callback. - * @param error The error message string to be displayed. - */ - protected void showCallbackNonExistentError(String error) { - showError(error); - } - - /** - * Broadcasts the given intent to all interested BroadcastReceivers. - */ - public void sendBroadcast(Intent intent) { - mActivity.sendBroadcast(intent); - } - - /** - * TODO(nileshagrawal): Stop returning Activity Context crbug.com/233440. - * @return Activity context. - */ - @Deprecated - public Context getContext() { - return mActivity; - } - - /** - * Saves the error messages that should be shown if any pending intents would return - * after the application has been put onPause. - * @param bundle The bundle to save the information in onPause - */ - public void saveInstanceState(Bundle bundle) { - bundle.putSerializable(WINDOW_CALLBACK_ERRORS, mIntentErrors); - } - - /** - * Restores the error messages that should be shown if any pending intents would return - * after the application has been put onPause. - * @param bundle The bundle to restore the information from onResume - */ - public void restoreInstanceState(Bundle bundle) { - if (bundle == null) return; - - Object errors = bundle.getSerializable(WINDOW_CALLBACK_ERRORS); - if (errors instanceof HashMap) { - @SuppressWarnings("unchecked") - HashMap<Integer, String> intentErrors = (HashMap<Integer, String>) errors; - mIntentErrors = intentErrors; - } - } - - /** - * Responds to the intent result if the intent was created by the native window. - * @param requestCode Request code of the requested intent. - * @param resultCode Result code of the requested intent. - * @param data The data returned by the intent. - * @return Boolean value of whether the intent was started by the native window. - */ - public boolean onActivityResult(int requestCode, int resultCode, Intent data) { - IntentCallback callback = mOutstandingIntents.get(requestCode); - mOutstandingIntents.delete(requestCode); - String errorMessage = mIntentErrors.remove(requestCode); - - if (callback != null) { - callback.onIntentCompleted(this, resultCode, - mActivity.getContentResolver(), data); - return true; - } else { - if (errorMessage != null) { - showCallbackNonExistentError(errorMessage); - return true; - } - } - return false; - } - - /** - * An interface that intent callback objects have to implement. - */ - public interface IntentCallback { - /** - * Handles the data returned by the requested intent. - * @param window A window reference. - * @param resultCode Result code of the requested intent. - * @param contentResolver An instance of ContentResolver class for accessing returned data. - * @param data The data returned by the intent. - */ - public void onIntentCompleted(WindowAndroid window, int resultCode, - ContentResolver contentResolver, Intent data); - } - - /** - * Destroys the c++ WindowAndroid object if one has been created. - */ - public void destroy() { - if (mNativeWindowAndroid != 0) { - nativeDestroy(mNativeWindowAndroid); - mNativeWindowAndroid = 0; - } - } - - /** - * Returns a pointer to the c++ AndroidWindow object and calls the initializer if - * the object has not been previously initialized. - * @return A pointer to the c++ AndroidWindow. - */ - public int getNativePointer() { - if (mNativeWindowAndroid == 0) { - mNativeWindowAndroid = nativeInit(); - } - return mNativeWindowAndroid; - } - - private native int nativeInit(); - private native void nativeDestroy(int nativeWindowAndroid); - -} diff --git a/chromium/ui/android/java/src/org/chromium/ui/autofill/AutofillListAdapter.java b/chromium/ui/android/java/src/org/chromium/ui/autofill/AutofillListAdapter.java deleted file mode 100644 index 62203dc70a8..00000000000 --- a/chromium/ui/android/java/src/org/chromium/ui/autofill/AutofillListAdapter.java +++ /dev/null @@ -1,54 +0,0 @@ -// 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. - - -package org.chromium.ui.autofill; - -import android.content.Context; -import android.text.TextUtils; - -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.TextView; - -import org.chromium.ui.R; - -import java.util.ArrayList; - -/** - * Autofill suggestion adapter for AutofillWindow. - */ -public class AutofillListAdapter extends ArrayAdapter<AutofillSuggestion> { - private Context mContext; - - AutofillListAdapter(Context context, ArrayList<AutofillSuggestion> objects) { - super(context, R.layout.autofill_text, objects); - mContext = context; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - View layout = convertView; - if (convertView == null) { - LayoutInflater inflater = - (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - layout = inflater.inflate(R.layout.autofill_text, null); - } - TextView labelView = (TextView) layout.findViewById(R.id.autofill_label); - labelView.setText(getItem(position).mLabel); - - TextView sublabelView = (TextView) layout.findViewById(R.id.autofill_sublabel); - CharSequence sublabel = getItem(position).mSublabel; - if (TextUtils.isEmpty(sublabel)) { - sublabelView.setVisibility(View.GONE); - } else { - sublabelView.setText(sublabel); - sublabelView.setVisibility(View.VISIBLE); - } - - return layout; - } -} diff --git a/chromium/ui/android/java/src/org/chromium/ui/autofill/AutofillPopup.java b/chromium/ui/android/java/src/org/chromium/ui/autofill/AutofillPopup.java deleted file mode 100644 index 0483b027215..00000000000 --- a/chromium/ui/android/java/src/org/chromium/ui/autofill/AutofillPopup.java +++ /dev/null @@ -1,214 +0,0 @@ -// 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. - -package org.chromium.ui.autofill; - -import android.content.Context; -import android.graphics.Paint; -import android.graphics.Rect; -import android.text.TextUtils; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnLayoutChangeListener; -import android.widget.AdapterView; -import android.widget.ListPopupWindow; -import android.widget.TextView; - -import java.util.ArrayList; - -import org.chromium.ui.R; -import org.chromium.ui.ViewAndroidDelegate; - -/** - * The Autofill suggestion popup that lists relevant suggestions. - */ -public class AutofillPopup extends ListPopupWindow implements AdapterView.OnItemClickListener { - - /** - * Constants defining types of Autofill suggestion entries. - * Has to be kept in sync with enum in WebAutofillClient.h - * - * Not supported: MenuItemIDWarningMessage, MenuItemIDSeparator, MenuItemIDClearForm, and - * MenuItemIDAutofillOptions. - */ - private static final int ITEM_ID_AUTOCOMPLETE_ENTRY = 0; - private static final int ITEM_ID_PASSWORD_ENTRY = -2; - private static final int ITEM_ID_DATA_LIST_ENTRY = -6; - - private static final int TEXT_PADDING_DP = 30; - - private final AutofillPopupDelegate mAutofillCallback; - private final Context mContext; - private final ViewAndroidDelegate mViewAndroidDelegate; - private View mAnchorView; - private float mAnchorWidth; - private float mAnchorHeight; - private float mAnchorX; - private float mAnchorY; - private Paint mLabelViewPaint; - private Paint mSublabelViewPaint; - private OnLayoutChangeListener mLayoutChangeListener; - - /** - * An interface to handle the touch interaction with an AutofillPopup object. - */ - public interface AutofillPopupDelegate { - /** - * Requests the controller to hide AutofillPopup. - */ - public void requestHide(); - - /** - * Handles the selection of an Autofill suggestion from an AutofillPopup. - * @param listIndex The index of the selected Autofill suggestion. - */ - public void suggestionSelected(int listIndex); - } - - /** - * Creates an AutofillWindow with specified parameters. - * @param context Application context. - * @param viewAndroidDelegate View delegate used to add and remove views. - * @param autofillCallback A object that handles the calls to the native AutofillPopupView. - */ - public AutofillPopup(Context context, ViewAndroidDelegate viewAndroidDelegate, - AutofillPopupDelegate autofillCallback) { - super(context, null, 0, R.style.AutofillPopupWindow); - mContext = context; - mViewAndroidDelegate = viewAndroidDelegate ; - mAutofillCallback = autofillCallback; - - setOnItemClickListener(this); - - mAnchorView = mViewAndroidDelegate.acquireAnchorView(); - mAnchorView.setId(R.id.autofill_popup_window); - mAnchorView.setTag(this); - - mViewAndroidDelegate.setAnchorViewPosition(mAnchorView, mAnchorX, mAnchorY, mAnchorWidth, - mAnchorHeight); - - mLayoutChangeListener = new OnLayoutChangeListener() { - @Override - public void onLayoutChange(View v, int left, int top, int right, int bottom, - int oldLeft, int oldTop, int oldRight, int oldBottom) { - if (v == mAnchorView) AutofillPopup.this.show(); - } - }; - - mAnchorView.addOnLayoutChangeListener(mLayoutChangeListener); - setAnchorView(mAnchorView); - } - - @Override - public void show() { - // An ugly hack to keep the popup from expanding on top of the keyboard. - setInputMethodMode(INPUT_METHOD_NEEDED); - super.show(); - } - - /** - * Sets the location and the size of the anchor view that the AutofillPopup will use to attach - * itself. - * @param x X coordinate of the top left corner of the anchor view. - * @param y Y coordinate of the top left corner of the anchor view. - * @param width The width of the anchor view. - * @param height The height of the anchor view. - */ - public void setAnchorRect(float x, float y, float width, float height) { - mAnchorWidth = width; - mAnchorHeight = height; - mAnchorX = x; - mAnchorY = y; - if (mAnchorView != null) { - mViewAndroidDelegate.setAnchorViewPosition(mAnchorView, mAnchorX, mAnchorY, - mAnchorWidth, mAnchorHeight); - } - } - - /** - * Sets the Autofill suggestions to display in the popup and shows the popup. - * @param suggestions Autofill suggestion data. - */ - public void show(AutofillSuggestion[] suggestions) { - // Remove the AutofillSuggestions with IDs that are not supported by Android - ArrayList<AutofillSuggestion> cleanedData = new ArrayList<AutofillSuggestion>(); - for (int i = 0; i < suggestions.length; i++) { - int itemId = suggestions[i].mUniqueId; - if (itemId > 0 || itemId == ITEM_ID_AUTOCOMPLETE_ENTRY || - itemId == ITEM_ID_PASSWORD_ENTRY || itemId == ITEM_ID_DATA_LIST_ENTRY) { - cleanedData.add(suggestions[i]); - } - } - setAdapter(new AutofillListAdapter(mContext, cleanedData)); - // Once the mAnchorRect is resized and placed correctly, it will show the Autofill popup. - mAnchorWidth = Math.max(getDesiredWidth(cleanedData), mAnchorWidth); - mViewAndroidDelegate.setAnchorViewPosition(mAnchorView, mAnchorX, mAnchorY, mAnchorWidth, - mAnchorHeight); - } - - /** - * Overrides the default dismiss behavior to request the controller to dismiss the view. - */ - @Override - public void dismiss() { - mAutofillCallback.requestHide(); - } - - /** - * Hides the popup and removes the anchor view from the ContainerView. - */ - public void hide() { - super.dismiss(); - mAnchorView.removeOnLayoutChangeListener(mLayoutChangeListener); - mAnchorView.setTag(null); - mViewAndroidDelegate.releaseAnchorView(mAnchorView); - } - - /** - * Get desired popup window width by calculating the maximum text length from Autofill data. - * @param data Autofill suggestion data. - * @return The popup window width in DIP. - */ - private float getDesiredWidth(ArrayList<AutofillSuggestion> data) { - if (mLabelViewPaint == null || mSublabelViewPaint == null) { - LayoutInflater inflater = - (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - View layout = inflater.inflate(R.layout.autofill_text, null); - TextView labelView = (TextView) layout.findViewById(R.id.autofill_label); - mLabelViewPaint = labelView.getPaint(); - TextView sublabelView = (TextView) layout.findViewById(R.id.autofill_sublabel); - mSublabelViewPaint = sublabelView.getPaint(); - } - - float maxTextWidth = 0; - Rect bounds = new Rect(); - for (int i = 0; i < data.size(); ++i) { - bounds.setEmpty(); - String label = data.get(i).mLabel; - if (!TextUtils.isEmpty(label)) { - mLabelViewPaint.getTextBounds(label, 0, label.length(), bounds); - } - float labelWidth = bounds.width(); - - bounds.setEmpty(); - String sublabel = data.get(i).mSublabel; - if (!TextUtils.isEmpty(sublabel)) { - mSublabelViewPaint.getTextBounds(sublabel, 0, sublabel.length(), bounds); - } - - float localMax = Math.max(labelWidth, bounds.width()); - maxTextWidth = Math.max(maxTextWidth, localMax); - } - // Scale it down to make it unscaled by screen density. - maxTextWidth = maxTextWidth / mContext.getResources().getDisplayMetrics().density; - // Adding padding. - return maxTextWidth + TEXT_PADDING_DP; - } - - @Override - public void onItemClick(AdapterView<?> parent, View view, int position, long id) { - mAutofillCallback.suggestionSelected(position); - } - -} diff --git a/chromium/ui/android/java/src/org/chromium/ui/autofill/AutofillSuggestion.java b/chromium/ui/android/java/src/org/chromium/ui/autofill/AutofillSuggestion.java deleted file mode 100644 index 51669ea5603..00000000000 --- a/chromium/ui/android/java/src/org/chromium/ui/autofill/AutofillSuggestion.java +++ /dev/null @@ -1,26 +0,0 @@ -// 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. - -package org.chromium.ui.autofill; - -/** - * Autofill suggestion container used to store information needed for each Autofill popup entry. - */ -public class AutofillSuggestion { - final String mLabel; - final String mSublabel; - final int mUniqueId; - - /** - * Constructs a Autofill suggestion container. - * @param name The name of the Autofill suggestion. - * @param label The describing label of the Autofill suggestion. - * @param uniqueId The unique id used to identify the Autofill suggestion. - */ - public AutofillSuggestion(String name, String label, int uniqueId) { - mLabel = name; - mSublabel = label; - mUniqueId = uniqueId; - } -}
\ No newline at end of file diff --git a/chromium/ui/android/java/src/org/chromium/ui/gfx/BitmapHelper.java b/chromium/ui/android/java/src/org/chromium/ui/gfx/BitmapHelper.java deleted file mode 100644 index 97511a176a8..00000000000 --- a/chromium/ui/android/java/src/org/chromium/ui/gfx/BitmapHelper.java +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2012 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. - -package org.chromium.ui.gfx; - -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import org.chromium.base.CalledByNative; -import org.chromium.base.JNINamespace; - -@JNINamespace("ui") -public class BitmapHelper { - @CalledByNative - public static Bitmap createBitmap(int width, int height) { - return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - } - - /** - * Decode and sample down a bitmap resource to the requested width and height. - * - * @param name The resource name of the bitmap to decode. - * @param reqWidth The requested width of the resulting bitmap. - * @param reqHeight The requested height of the resulting bitmap. - * @return A bitmap sampled down from the original with the same aspect ratio and dimensions. - * that are equal to or greater than the requested width and height. - */ - @CalledByNative - private static Bitmap decodeDrawableResource(String name, - int reqWidth, - int reqHeight) { - Resources res = Resources.getSystem(); - int resId = res.getIdentifier(name, null, null); - - final BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeResource(res, resId, options); - - options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); - - options.inJustDecodeBounds = false; - return BitmapFactory.decodeResource(res, resId, options); - } - - // http://developer.android.com/training/displaying-bitmaps/load-bitmap.html - private static int calculateInSampleSize(BitmapFactory.Options options, - int reqWidth, - int reqHeight) { - // Raw height and width of image - final int height = options.outHeight; - final int width = options.outWidth; - int inSampleSize = 1; - - if (height > reqHeight || width > reqWidth) { - - // Calculate ratios of height and width to requested height and width - final int heightRatio = Math.round((float) height / (float) reqHeight); - final int widthRatio = Math.round((float) width / (float) reqWidth); - - // Choose the smallest ratio as inSampleSize value, this will guarantee - // a final image with both dimensions larger than or equal to the - // requested height and width. - inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; - } - - return inSampleSize; - } -} diff --git a/chromium/ui/android/java/src/org/chromium/ui/gfx/DeviceDisplayInfo.java b/chromium/ui/android/java/src/org/chromium/ui/gfx/DeviceDisplayInfo.java deleted file mode 100644 index 088c9c2476e..00000000000 --- a/chromium/ui/android/java/src/org/chromium/ui/gfx/DeviceDisplayInfo.java +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright (c) 2012 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. - -package org.chromium.ui.gfx; - -import android.content.Context; -import android.graphics.PixelFormat; -import android.os.Build; -import android.util.DisplayMetrics; -import android.view.Display; -import android.view.WindowManager; - -import org.chromium.base.CalledByNative; -import org.chromium.base.JNINamespace; - -/** - * This class facilitates access to android information typically only - * available using the Java SDK, including {@link Display} properties. - * - * Currently the information consists of very raw display information (height, width, DPI scale) - * regarding the main display. - */ -@JNINamespace("gfx") -public class DeviceDisplayInfo { - - - private final Context mAppContext; - private final WindowManager mWinManager; - - private DeviceDisplayInfo(Context context) { - mAppContext = context.getApplicationContext(); - mWinManager = (WindowManager) mAppContext.getSystemService(Context.WINDOW_SERVICE); - } - - /** - * @return Display height in physical pixels. - */ - @CalledByNative - public int getDisplayHeight() { - return getMetrics().heightPixels; - } - - /** - * @return Display width in physical pixels. - */ - @CalledByNative - public int getDisplayWidth() { - return getMetrics().widthPixels; - } - - @SuppressWarnings("deprecation") - private int getPixelFormat() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { - return getDisplay().getPixelFormat(); - } - // JellyBean MR1 and later always uses RGBA_8888. - return PixelFormat.RGBA_8888; - } - - /** - * @return Bits per pixel. - */ - @CalledByNative - public int getBitsPerPixel() { - int format = getPixelFormat(); - PixelFormat info = new PixelFormat(); - PixelFormat.getPixelFormatInfo(format, info); - return info.bitsPerPixel; - } - - /** - * @return Bits per component. - */ - @SuppressWarnings("deprecation") - @CalledByNative - public int getBitsPerComponent() { - int format = getPixelFormat(); - switch (format) { - case PixelFormat.RGBA_4444: - return 4; - - case PixelFormat.RGBA_5551: - return 5; - - case PixelFormat.RGBA_8888: - case PixelFormat.RGBX_8888: - case PixelFormat.RGB_888: - return 8; - - case PixelFormat.RGB_332: - return 2; - - case PixelFormat.RGB_565: - return 5; - - // Non-RGB formats. - case PixelFormat.A_8: - case PixelFormat.LA_88: - case PixelFormat.L_8: - return 0; - - // Unknown format. Use 8 as a sensible default. - default: - return 8; - } - } - - /** - * @return A scaling factor for the Density Independent Pixel unit. - * 1.0 is 160dpi, 0.75 is 120dpi, 2.0 is 320dpi. - */ - @CalledByNative - public double getDIPScale() { - return getMetrics().density; - } - - private Display getDisplay() { - return mWinManager.getDefaultDisplay(); - } - - private DisplayMetrics getMetrics() { - return mAppContext.getResources().getDisplayMetrics(); - } - - /** - * Creates DeviceDisplayInfo for a given Context. - * @param context A context to use. - * @return DeviceDisplayInfo associated with a given Context. - */ - @CalledByNative - public static DeviceDisplayInfo create(Context context) { - return new DeviceDisplayInfo(context); - } -} diff --git a/chromium/ui/android/java/src/org/chromium/ui/gfx/SurfaceTextureBridge.java b/chromium/ui/android/java/src/org/chromium/ui/gfx/SurfaceTextureBridge.java deleted file mode 100644 index 2333a01bb2f..00000000000 --- a/chromium/ui/android/java/src/org/chromium/ui/gfx/SurfaceTextureBridge.java +++ /dev/null @@ -1,64 +0,0 @@ -// 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. - -package org.chromium.ui.gfx; - -import android.graphics.SurfaceTexture; -import android.os.Build; - -import org.chromium.base.CalledByNative; -import org.chromium.base.JNINamespace; - -/** - * Wrapper class for the underlying platform's SurfaceTexture in order to - * provide a stable JNI API. - */ -@JNINamespace("gfx") -class SurfaceTextureBridge { - @CalledByNative - private static SurfaceTexture create(int textureId) { - return new SurfaceTexture(textureId); - } - - @CalledByNative - private static void destroy(SurfaceTexture surfaceTexture) { - surfaceTexture.setOnFrameAvailableListener(null); - surfaceTexture.release(); - } - - @CalledByNative - private static void setFrameAvailableCallback(SurfaceTexture surfaceTexture, - int nativeSurfaceTextureListener) { - surfaceTexture.setOnFrameAvailableListener( - new SurfaceTextureListener(nativeSurfaceTextureListener)); - } - - @CalledByNative - private static void updateTexImage(SurfaceTexture surfaceTexture) { - surfaceTexture.updateTexImage(); - } - - @CalledByNative - private static void setDefaultBufferSize(SurfaceTexture surfaceTexture, int width, - int height) { - surfaceTexture.setDefaultBufferSize(width, height); - } - - @CalledByNative - private static void getTransformMatrix(SurfaceTexture surfaceTexture, float[] matrix) { - surfaceTexture.getTransformMatrix(matrix); - } - - @CalledByNative - private static void attachToGLContext(SurfaceTexture surfaceTexture, int texName) { - assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; - surfaceTexture.attachToGLContext(texName); - } - - @CalledByNative - private static void detachFromGLContext(SurfaceTexture surfaceTexture) { - assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; - surfaceTexture.detachFromGLContext(); - } -}
\ No newline at end of file diff --git a/chromium/ui/android/java/src/org/chromium/ui/gfx/SurfaceTextureListener.java b/chromium/ui/android/java/src/org/chromium/ui/gfx/SurfaceTextureListener.java deleted file mode 100644 index 1b77370e4b6..00000000000 --- a/chromium/ui/android/java/src/org/chromium/ui/gfx/SurfaceTextureListener.java +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 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. - -package org.chromium.ui.gfx; - -import android.graphics.SurfaceTexture; - -import org.chromium.base.JNINamespace; - -/** - * Listener to an android SurfaceTexture object for frame availability. - */ -@JNINamespace("gfx") -class SurfaceTextureListener implements SurfaceTexture.OnFrameAvailableListener { - // Used to determine the class instance to dispatch the native call to. - private final int mNativeSurfaceTextureListener; - - SurfaceTextureListener(int nativeSurfaceTextureListener) { - assert nativeSurfaceTextureListener != 0; - mNativeSurfaceTextureListener = nativeSurfaceTextureListener; - } - - @Override - public void onFrameAvailable(SurfaceTexture surfaceTexture) { - nativeFrameAvailable(mNativeSurfaceTextureListener); - } - - @Override - protected void finalize() throws Throwable { - try { - nativeDestroy(mNativeSurfaceTextureListener); - } finally { - super.finalize(); - } - } - - private native void nativeFrameAvailable(int nativeSurfaceTextureListener); - private native void nativeDestroy(int nativeSurfaceTextureListener); -} diff --git a/chromium/ui/android/java/strings/android_ui_strings.grd b/chromium/ui/android/java/strings/android_ui_strings.grd deleted file mode 100644 index ee2f2d4cdf7..00000000000 --- a/chromium/ui/android/java/strings/android_ui_strings.grd +++ /dev/null @@ -1,125 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<grit current_release="1" latest_public_release="0"> - <release allow_pseudo="false" seq="1"> - <messages fallback_to_english="true"> - <message desc="Error shown when the browser is restarted due to low memory during a file picker operation. [CHAR-LIMIT=NONE]" name="IDS_LOW_MEMORY_ERROR"> - Unable to complete previous operation due to low memory - </message> - <message desc="Toast when the browser is unable to open a file for upload. [CHAR-LIMIT=32]" name="IDS_OPENING_FILE_ERROR"> - Failed to open selected file - </message> - <message desc="Text for ColorPicker button to go to advanced view. [CHAR-LIMIT=20]" name="IDS_COLOR_PICKER_BUTTON_MORE"> - More - </message> - <message desc="Label for hue slider in ColorPicker." name="IDS_COLOR_PICKER_HUE"> - Hue - </message> - <message desc="Label for saturation slider in ColorPicker." name="IDS_COLOR_PICKER_SATURATION"> - Saturation - </message> - <message desc="Label for value slider in ColorPicker." name="IDS_COLOR_PICKER_VALUE"> - Value - </message> - <message desc="Label for button in ColorPicker dialog for user to accept the currently chosen color. [CHAR-LIMIT=20]" name="IDS_COLOR_PICKER_BUTTON_SET"> - Set - </message> - <message desc="Label for button in ColorPicker dialog for user to cancel picking a color. [CHAR-LIMIT=20]" name="IDS_COLOR_PICKER_BUTTON_CANCEL"> - Cancel - </message> - <message desc="Title of ColorPicker dialog. [CHAR-LIMIT=20]" name="IDS_COLOR_PICKER_DIALOG_TITLE"> - Select color - </message> - </messages> - </release> - <translations> - <file lang="am" path="translations/android_ui_strings_am.xtb" /> - <file lang="ar" path="translations/android_ui_strings_ar.xtb" /> - <file lang="bg" path="translations/android_ui_strings_bg.xtb" /> - <file lang="ca" path="translations/android_ui_strings_ca.xtb" /> - <file lang="cs" path="translations/android_ui_strings_cs.xtb" /> - <file lang="da" path="translations/android_ui_strings_da.xtb" /> - <file lang="de" path="translations/android_ui_strings_de.xtb" /> - <file lang="el" path="translations/android_ui_strings_el.xtb" /> - <file lang="en-GB" path="translations/android_ui_strings_en-GB.xtb" /> - <file lang="es" path="translations/android_ui_strings_es.xtb" /> - <file lang="es-419" path="translations/android_ui_strings_es-419.xtb" /> - <file lang="fa" path="translations/android_ui_strings_fa.xtb" /> - <file lang="fi" path="translations/android_ui_strings_fi.xtb" /> - <file lang="fil" path="translations/android_ui_strings_fil.xtb" /> - <file lang="fr" path="translations/android_ui_strings_fr.xtb" /> - <file lang="hi" path="translations/android_ui_strings_hi.xtb" /> - <file lang="hr" path="translations/android_ui_strings_hr.xtb" /> - <file lang="hu" path="translations/android_ui_strings_hu.xtb" /> - <file lang="id" path="translations/android_ui_strings_id.xtb" /> - <file lang="it" path="translations/android_ui_strings_it.xtb" /> - <file lang="iw" path="translations/android_ui_strings_iw.xtb" /> - <file lang="ja" path="translations/android_ui_strings_ja.xtb" /> - <file lang="ko" path="translations/android_ui_strings_ko.xtb" /> - <file lang="lt" path="translations/android_ui_strings_lt.xtb" /> - <file lang="lv" path="translations/android_ui_strings_lv.xtb" /> - <file lang="nl" path="translations/android_ui_strings_nl.xtb" /> - <file lang="no" path="translations/android_ui_strings_no.xtb" /> - <file lang="pl" path="translations/android_ui_strings_pl.xtb" /> - <file lang="pt-BR" path="translations/android_ui_strings_pt-BR.xtb" /> - <file lang="pt-PT" path="translations/android_ui_strings_pt-PT.xtb" /> - <file lang="ro" path="translations/android_ui_strings_ro.xtb" /> - <file lang="ru" path="translations/android_ui_strings_ru.xtb" /> - <file lang="sk" path="translations/android_ui_strings_sk.xtb" /> - <file lang="sl" path="translations/android_ui_strings_sl.xtb" /> - <file lang="sr" path="translations/android_ui_strings_sr.xtb" /> - <file lang="sv" path="translations/android_ui_strings_sv.xtb" /> - <file lang="sw" path="translations/android_ui_strings_sw.xtb" /> - <file lang="th" path="translations/android_ui_strings_th.xtb" /> - <file lang="tr" path="translations/android_ui_strings_tr.xtb" /> - <file lang="uk" path="translations/android_ui_strings_uk.xtb" /> - <file lang="vi" path="translations/android_ui_strings_vi.xtb" /> - <file lang="zh-CN" path="translations/android_ui_strings_zh-CN.xtb" /> - <file lang="zh-TW" path="translations/android_ui_strings_zh-TW.xtb" /> - </translations> - <outputs> - <output filename="values-am/android_ui_strings.xml" lang="am" type="android" /> - <output filename="values-ar/android_ui_strings.xml" lang="ar" type="android" /> - <output filename="values-bg/android_ui_strings.xml" lang="bg" type="android" /> - <output filename="values-ca/android_ui_strings.xml" lang="ca" type="android" /> - <output filename="values-cs/android_ui_strings.xml" lang="cs" type="android" /> - <output filename="values-da/android_ui_strings.xml" lang="da" type="android" /> - <output filename="values-de/android_ui_strings.xml" lang="de" type="android" /> - <output filename="values-el/android_ui_strings.xml" lang="el" type="android" /> - <output filename="values/android_ui_strings.xml" lang="en" type="android" /> - <output filename="values-en-rGB/android_ui_strings.xml" lang="en-GB" type="android" /> - <output filename="values-es/android_ui_strings.xml" lang="es" type="android" /> - <output filename="values-es-rUS/android_ui_strings.xml" lang="es-419" type="android" /> - <output filename="values-fa/android_ui_strings.xml" lang="fa" type="android" /> - <output filename="values-fi/android_ui_strings.xml" lang="fi" type="android" /> - <output filename="values-tl/android_ui_strings.xml" lang="fil" type="android" /> - <output filename="values-fr/android_ui_strings.xml" lang="fr" type="android" /> - <output filename="values-hi/android_ui_strings.xml" lang="hi" type="android" /> - <output filename="values-hr/android_ui_strings.xml" lang="hr" type="android" /> - <output filename="values-hu/android_ui_strings.xml" lang="hu" type="android" /> - <output filename="values-in/android_ui_strings.xml" lang="id" type="android" /> - <output filename="values-it/android_ui_strings.xml" lang="it" type="android" /> - <output filename="values-iw/android_ui_strings.xml" lang="iw" type="android" /> - <output filename="values-ja/android_ui_strings.xml" lang="ja" type="android" /> - <output filename="values-ko/android_ui_strings.xml" lang="ko" type="android" /> - <output filename="values-lt/android_ui_strings.xml" lang="lt" type="android" /> - <output filename="values-lv/android_ui_strings.xml" lang="lv" type="android" /> - <output filename="values-nl/android_ui_strings.xml" lang="nl" type="android" /> - <output filename="values-nb/android_ui_strings.xml" lang="no" type="android" /> - <output filename="values-pl/android_ui_strings.xml" lang="pl" type="android" /> - <output filename="values-pt-rBR/android_ui_strings.xml" lang="pt-BR" type="android" /> - <output filename="values-pt-rPT/android_ui_strings.xml" lang="pt-PT" type="android" /> - <output filename="values-ro/android_ui_strings.xml" lang="ro" type="android" /> - <output filename="values-ru/android_ui_strings.xml" lang="ru" type="android" /> - <output filename="values-sk/android_ui_strings.xml" lang="sk" type="android" /> - <output filename="values-sl/android_ui_strings.xml" lang="sl" type="android" /> - <output filename="values-sr/android_ui_strings.xml" lang="sr" type="android" /> - <output filename="values-sv/android_ui_strings.xml" lang="sv" type="android" /> - <output filename="values-sw/android_ui_strings.xml" lang="sw" type="android" /> - <output filename="values-th/android_ui_strings.xml" lang="th" type="android" /> - <output filename="values-tr/android_ui_strings.xml" lang="tr" type="android" /> - <output filename="values-uk/android_ui_strings.xml" lang="uk" type="android" /> - <output filename="values-vi/android_ui_strings.xml" lang="vi" type="android" /> - <output filename="values-zh-rCN/android_ui_strings.xml" lang="zh-CN" type="android" /> - <output filename="values-zh-rTW/android_ui_strings.xml" lang="zh-TW" type="android" /> - </outputs> -</grit> diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_am.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_am.xtb deleted file mode 100644 index 5009378fbdb..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_am.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="am"> -<translation id="7658239707568436148">ሰርዝ</translation> -<translation id="6727102863431372879">አዘጋጅ</translation> -<translation id="6042308850641462728">ተጨማሪ</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_ar.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_ar.xtb deleted file mode 100644 index 20d74b0896c..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_ar.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="ar"> -<translation id="7658239707568436148">إلغاء</translation> -<translation id="6727102863431372879">تعيين</translation> -<translation id="6042308850641462728">المزيد</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_bg.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_bg.xtb deleted file mode 100644 index 3f7f0eebb0c..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_bg.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="bg"> -<translation id="7658239707568436148">Отказ</translation> -<translation id="6727102863431372879">Задаване</translation> -<translation id="6042308850641462728">Още</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_ca.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_ca.xtb deleted file mode 100644 index b19aac4fc3e..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_ca.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="ca"> -<translation id="7658239707568436148">Cancel·la</translation> -<translation id="6727102863431372879">Configura</translation> -<translation id="6042308850641462728">Més</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_cs.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_cs.xtb deleted file mode 100644 index b39bcf81dcc..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_cs.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="cs"> -<translation id="7658239707568436148">Zrušit</translation> -<translation id="6727102863431372879">Nastavit</translation> -<translation id="6042308850641462728">Více</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_da.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_da.xtb deleted file mode 100644 index bdc4393844d..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_da.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="da"> -<translation id="7658239707568436148">Annuller</translation> -<translation id="6727102863431372879">Angiv</translation> -<translation id="6042308850641462728">Mere</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_de.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_de.xtb deleted file mode 100644 index 3226fe1c64b..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_de.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="de"> -<translation id="7658239707568436148">Abbrechen</translation> -<translation id="6727102863431372879">Festlegen</translation> -<translation id="6042308850641462728">Mehr</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_el.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_el.xtb deleted file mode 100644 index 23bcfbbc582..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_el.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="el"> -<translation id="7658239707568436148">Ακύρωση</translation> -<translation id="6727102863431372879">Ορισμός</translation> -<translation id="6042308850641462728">Περισσότερα</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_en-GB.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_en-GB.xtb deleted file mode 100644 index 760ecfbba68..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_en-GB.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="en-GB"> -<translation id="7658239707568436148">Cancel</translation> -<translation id="6727102863431372879">Set</translation> -<translation id="6042308850641462728">More</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_es-419.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_es-419.xtb deleted file mode 100644 index a72fce86599..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_es-419.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="es-419"> -<translation id="7658239707568436148">Cancelar</translation> -<translation id="6727102863431372879">Establecer</translation> -<translation id="6042308850641462728">Más</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_es.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_es.xtb deleted file mode 100644 index 13d9dcb1077..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_es.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="es"> -<translation id="7658239707568436148">Cancelar</translation> -<translation id="6727102863431372879">Establecer</translation> -<translation id="6042308850641462728">Más</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_fa.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_fa.xtb deleted file mode 100644 index a5250a0b344..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_fa.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="fa"> -<translation id="7658239707568436148">لغو</translation> -<translation id="6727102863431372879">تنظیم</translation> -<translation id="6042308850641462728">بیشتر</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_fi.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_fi.xtb deleted file mode 100644 index 432a6308fe4..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_fi.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="fi"> -<translation id="7658239707568436148">Peruuta</translation> -<translation id="6727102863431372879">Aseta</translation> -<translation id="6042308850641462728">Lisää</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_fil.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_fil.xtb deleted file mode 100644 index 43d1a8dc4ba..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_fil.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="fil"> -<translation id="7658239707568436148">Kanselahin</translation> -<translation id="6727102863431372879">Itakda</translation> -<translation id="6042308850641462728">Higit pa</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_fr.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_fr.xtb deleted file mode 100644 index 0996b594dd4..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_fr.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="fr"> -<translation id="7658239707568436148">Annuler</translation> -<translation id="6727102863431372879">Définir</translation> -<translation id="6042308850641462728">Plus</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_hi.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_hi.xtb deleted file mode 100644 index ecd9dfd37bd..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_hi.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="hi"> -<translation id="7658239707568436148">रद्द करें</translation> -<translation id="6727102863431372879">सेट करें</translation> -<translation id="6042308850641462728">अधिक</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_hr.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_hr.xtb deleted file mode 100644 index 39ab27b13b8..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_hr.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="hr"> -<translation id="7658239707568436148">Odustani</translation> -<translation id="6727102863431372879">Postavi</translation> -<translation id="6042308850641462728">Više</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_hu.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_hu.xtb deleted file mode 100644 index cf229bc45dd..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_hu.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="hu"> -<translation id="7658239707568436148">Mégse</translation> -<translation id="6727102863431372879">Beállítás</translation> -<translation id="6042308850641462728">Hosszabban</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_id.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_id.xtb deleted file mode 100644 index 7f11b4549d6..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_id.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="id"> -<translation id="7658239707568436148">Batal</translation> -<translation id="6727102863431372879">Setel</translation> -<translation id="6042308850641462728">Lainnya</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_it.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_it.xtb deleted file mode 100644 index 3bd89fe29f6..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_it.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="it"> -<translation id="7658239707568436148">Annulla</translation> -<translation id="6727102863431372879">Imposta</translation> -<translation id="6042308850641462728">Più</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_iw.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_iw.xtb deleted file mode 100644 index ea0a9849a65..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_iw.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="iw"> -<translation id="7658239707568436148">ביטול</translation> -<translation id="6727102863431372879">הגדר</translation> -<translation id="6042308850641462728">עוד</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_ja.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_ja.xtb deleted file mode 100644 index 18989640fd4..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_ja.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="ja"> -<translation id="7658239707568436148">キャンセル</translation> -<translation id="6727102863431372879">設定</translation> -<translation id="6042308850641462728">詳細表示</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_ko.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_ko.xtb deleted file mode 100644 index 3667057117d..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_ko.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="ko"> -<translation id="7658239707568436148">취소</translation> -<translation id="6727102863431372879">설정</translation> -<translation id="6042308850641462728">더보기</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_lt.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_lt.xtb deleted file mode 100644 index 73968166e3d..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_lt.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="lt"> -<translation id="7658239707568436148">Atšaukti</translation> -<translation id="6727102863431372879">Nustatyti</translation> -<translation id="6042308850641462728">Daugiau</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_lv.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_lv.xtb deleted file mode 100644 index 4d9f44c4938..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_lv.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="lv"> -<translation id="7658239707568436148">Atcelt</translation> -<translation id="6727102863431372879">Iestatīt</translation> -<translation id="6042308850641462728">Vairāk</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_nl.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_nl.xtb deleted file mode 100644 index c3a47d4977a..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_nl.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="nl"> -<translation id="7658239707568436148">Annuleren</translation> -<translation id="6727102863431372879">Instellen</translation> -<translation id="6042308850641462728">Meer</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_no.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_no.xtb deleted file mode 100644 index c91bc537447..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_no.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="no"> -<translation id="7658239707568436148">Avbryt</translation> -<translation id="6727102863431372879">Angi</translation> -<translation id="6042308850641462728">Mer</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_pl.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_pl.xtb deleted file mode 100644 index 1fa6f0e3650..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_pl.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="pl"> -<translation id="7658239707568436148">Anuluj</translation> -<translation id="6727102863431372879">Ustaw</translation> -<translation id="6042308850641462728">Więcej</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_pt-BR.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_pt-BR.xtb deleted file mode 100644 index 0c5f3f8a018..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_pt-BR.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="pt-BR"> -<translation id="7658239707568436148">Cancelar</translation> -<translation id="6727102863431372879">Definir</translation> -<translation id="6042308850641462728">Mais</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_pt-PT.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_pt-PT.xtb deleted file mode 100644 index 2f315afe1f0..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_pt-PT.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="pt-PT"> -<translation id="7658239707568436148">Cancelar</translation> -<translation id="6727102863431372879">Definir</translation> -<translation id="6042308850641462728">Mais</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_ro.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_ro.xtb deleted file mode 100644 index e0b2c506830..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_ro.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="ro"> -<translation id="7658239707568436148">Anulaţi</translation> -<translation id="6727102863431372879">Setați</translation> -<translation id="6042308850641462728">Mai mult</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_ru.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_ru.xtb deleted file mode 100644 index 827ac4b0dd2..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_ru.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="ru"> -<translation id="7658239707568436148">Отмена</translation> -<translation id="6727102863431372879">Установить</translation> -<translation id="6042308850641462728">Подробнее...</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_sk.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_sk.xtb deleted file mode 100644 index 50599a2f56c..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_sk.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="sk"> -<translation id="7658239707568436148">Zrušiť</translation> -<translation id="6727102863431372879">Nastaviť</translation> -<translation id="6042308850641462728">Viac</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_sl.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_sl.xtb deleted file mode 100644 index 57093451693..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_sl.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="sl"> -<translation id="7658239707568436148">Prekliči</translation> -<translation id="6727102863431372879">Nastavi</translation> -<translation id="6042308850641462728">Več</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_sr.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_sr.xtb deleted file mode 100644 index 9475544e08d..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_sr.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="sr"> -<translation id="7658239707568436148">Откажи</translation> -<translation id="6727102863431372879">Постави</translation> -<translation id="6042308850641462728">Више</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_sv.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_sv.xtb deleted file mode 100644 index 092959a0d06..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_sv.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="sv"> -<translation id="7658239707568436148">Avbryt</translation> -<translation id="6727102863431372879">Ange</translation> -<translation id="6042308850641462728">Mer</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_sw.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_sw.xtb deleted file mode 100644 index 1de7db27052..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_sw.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="sw"> -<translation id="7658239707568436148">Ghairi</translation> -<translation id="6727102863431372879">Weka</translation> -<translation id="6042308850641462728">Zaidi</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_th.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_th.xtb deleted file mode 100644 index d8aec042ac6..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_th.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="th"> -<translation id="7658239707568436148">ยกเลิก</translation> -<translation id="6727102863431372879">ตั้งค่า</translation> -<translation id="6042308850641462728">เพิ่มเติม</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_tr.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_tr.xtb deleted file mode 100644 index 2a37f797deb..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_tr.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="tr"> -<translation id="7658239707568436148">İptal</translation> -<translation id="6727102863431372879">Ayarla</translation> -<translation id="6042308850641462728">Daha fazla</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_uk.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_uk.xtb deleted file mode 100644 index b9a0ae2ab81..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_uk.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="uk"> -<translation id="7658239707568436148">Скасувати</translation> -<translation id="6727102863431372879">Встановити</translation> -<translation id="6042308850641462728">Більше</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_vi.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_vi.xtb deleted file mode 100644 index c66fb60ae74..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_vi.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="vi"> -<translation id="7658239707568436148">Hủy</translation> -<translation id="6727102863431372879">Đặt</translation> -<translation id="6042308850641462728">Thêm</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_zh-CN.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_zh-CN.xtb deleted file mode 100644 index 8228c71b152..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_zh-CN.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="zh-CN"> -<translation id="7658239707568436148">取消</translation> -<translation id="6727102863431372879">设置</translation> -<translation id="6042308850641462728">更多</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/java/strings/translations/android_ui_strings_zh-TW.xtb b/chromium/ui/android/java/strings/translations/android_ui_strings_zh-TW.xtb deleted file mode 100644 index edf79b55e95..00000000000 --- a/chromium/ui/android/java/strings/translations/android_ui_strings_zh-TW.xtb +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE translationbundle> -<translationbundle lang="zh-TW"> -<translation id="7658239707568436148">取消</translation> -<translation id="6727102863431372879">設定</translation> -<translation id="6042308850641462728">詳細資訊</translation> -</translationbundle>
\ No newline at end of file diff --git a/chromium/ui/android/ui_jni_registrar.cc b/chromium/ui/android/ui_jni_registrar.cc deleted file mode 100644 index 8216e01578e..00000000000 --- a/chromium/ui/android/ui_jni_registrar.cc +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2012 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 "ui/android/ui_jni_registrar.h" - -#include "base/android/jni_android.h" -#include "base/android/jni_registrar.h" -#include "ui/android/view_android.h" -#include "ui/android/window_android.h" -#include "ui/base/clipboard/clipboard_android_initialization.h" -#include "ui/base/l10n/l10n_util_android.h" -#include "ui/gfx/android/device_display_info.h" -#include "ui/gfx/android/java_bitmap.h" - -namespace ui { -namespace android { - -static base::android::RegistrationMethod kUiRegisteredMethods[] = { - { "Clipboard", ui::RegisterClipboardAndroid }, - { "DeviceDisplayInfo", gfx::DeviceDisplayInfo::RegisterDeviceDisplayInfo }, - { "JavaBitmap", gfx::JavaBitmap::RegisterJavaBitmap }, - { "LocalizationUtils", l10n_util::RegisterLocalizationUtil }, - { "ViewAndroid", ui::ViewAndroid::RegisterViewAndroid }, - { "WindowAndroid", ui::WindowAndroid::RegisterWindowAndroid }, -}; - -bool RegisterJni(JNIEnv* env) { - return RegisterNativeMethods(env, kUiRegisteredMethods, - arraysize(kUiRegisteredMethods)); -} - -} // namespace android -} // namespace ui diff --git a/chromium/ui/android/ui_jni_registrar.h b/chromium/ui/android/ui_jni_registrar.h deleted file mode 100644 index f40ed407823..00000000000 --- a/chromium/ui/android/ui_jni_registrar.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef UI_ANDROID_UI_JNI_REGISTRAR_H_ -#define UI_ANDROID_UI_JNI_REGISTRAR_H_ - -#include <jni.h> - -#include "ui/base/ui_export.h" - -namespace ui { -namespace android { - -// Register all JNI bindings necessary for chrome. -UI_EXPORT bool RegisterJni(JNIEnv* env); - -} // namespace android -} // namespace ui - -#endif // UI_ANDROID_UI_JNI_REGISTRAR_H_ diff --git a/chromium/ui/android/window_android.cc b/chromium/ui/android/window_android.cc index 1f2ccb2f972..439268fd336 100644 --- a/chromium/ui/android/window_android.cc +++ b/chromium/ui/android/window_android.cc @@ -5,6 +5,7 @@ #include "ui/android/window_android.h" #include "base/android/jni_android.h" +#include "base/android/jni_array.h" #include "base/android/jni_helper.h" #include "base/android/scoped_java_ref.h" #include "jni/WindowAndroid_jni.h" @@ -33,6 +34,22 @@ bool WindowAndroid::RegisterWindowAndroid(JNIEnv* env) { WindowAndroid::~WindowAndroid() { } +bool WindowAndroid::GrabSnapshot( + int content_x, int content_y, int width, int height, + std::vector<unsigned char>* png_representation) { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jbyteArray> result = + Java_WindowAndroid_grabSnapshot(env, GetJavaObject().obj(), + content_x + content_offset_.x(), + content_y + content_offset_.y(), + width, height); + if (result.is_null()) + return false; + base::android::JavaByteArrayToByteVector( + env, result.obj(), png_representation); + return true; +} + // ---------------------------------------------------------------------------- // Native JNI methods // ---------------------------------------------------------------------------- diff --git a/chromium/ui/android/window_android.h b/chromium/ui/android/window_android.h index c1c5c44c2d2..14b1f09e222 100644 --- a/chromium/ui/android/window_android.h +++ b/chromium/ui/android/window_android.h @@ -6,9 +6,11 @@ #define UI_ANDROID_WINDOW_ANDROID_H_ #include <jni.h> +#include <vector> #include "base/android/jni_helper.h" #include "base/android/scoped_java_ref.h" #include "ui/base/ui_export.h" +#include "ui/gfx/vector2d_f.h" namespace ui { @@ -23,10 +25,20 @@ class UI_EXPORT WindowAndroid { static bool RegisterWindowAndroid(JNIEnv* env); + // The content offset is used to translate snapshots to the correct part of + // the window. + void set_content_offset(const gfx::Vector2dF& content_offset) { + content_offset_ = content_offset; + } + + bool GrabSnapshot(int content_x, int content_y, int width, int height, + std::vector<unsigned char>* png_representation); + private: ~WindowAndroid(); JavaObjectWeakGlobalRef weak_java_window_; + gfx::Vector2dF content_offset_; DISALLOW_COPY_AND_ASSIGN(WindowAndroid); }; diff --git a/chromium/ui/app_list/app_list.gyp b/chromium/ui/app_list/app_list.gyp index 35b4663a624..1d968712349 100644 --- a/chromium/ui/app_list/app_list.gyp +++ b/chromium/ui/app_list/app_list.gyp @@ -36,7 +36,6 @@ 'app_list_model.h', 'app_list_model_observer.h', 'app_list_view_delegate.h', - 'apps_grid_view_delegate.h', 'cocoa/app_list_pager_view.h', 'cocoa/app_list_pager_view.mm', 'cocoa/app_list_view_controller.h', @@ -58,8 +57,6 @@ 'cocoa/apps_search_results_model_bridge.mm', 'cocoa/blue_label_button.h', 'cocoa/blue_label_button.mm', - 'cocoa/current_user_menu_item_view.h', - 'cocoa/current_user_menu_item_view.mm', 'cocoa/item_drag_controller.h', 'cocoa/item_drag_controller.mm', 'cocoa/scroll_view_with_no_scrollbars.h', @@ -72,13 +69,10 @@ 'search_box_model.cc', 'search_box_model.h', 'search_box_model_observer.h', - 'search_box_view_delegate.h', 'search_result.cc', 'search_result.h', - 'search_result_list_view_delegate.h', 'signin_delegate.cc', 'signin_delegate.h', - 'signin_delegate_observer.h', 'views/app_list_background.cc', 'views/app_list_background.h', 'views/app_list_drag_and_drop_host.h', @@ -92,6 +86,7 @@ 'views/app_list_view.h', 'views/apps_grid_view.cc', 'views/apps_grid_view.h', + 'views/apps_grid_view_delegate.h', 'views/cached_label.cc', 'views/cached_label.h', 'views/contents_view.cc', @@ -104,10 +99,12 @@ 'views/pulsing_block_view.h', 'views/search_box_view.cc', 'views/search_box_view.h', + 'views/search_box_view_delegate.h', 'views/search_result_actions_view.cc', 'views/search_result_actions_view.h', 'views/search_result_list_view.cc', 'views/search_result_list_view.h', + 'views/search_result_list_view_delegate.h', 'views/search_result_view.cc', 'views/search_result_view.h', 'views/search_result_view_delegate.h', diff --git a/chromium/ui/app_list/app_list_item_model.cc b/chromium/ui/app_list/app_list_item_model.cc index c9aedb59be8..65b87a33ab4 100644 --- a/chromium/ui/app_list/app_list_item_model.cc +++ b/chromium/ui/app_list/app_list_item_model.cc @@ -24,11 +24,13 @@ void AppListItemModel::SetIcon(const gfx::ImageSkia& icon, bool has_shadow) { FOR_EACH_OBSERVER(AppListItemModelObserver, observers_, ItemIconChanged()); } -void AppListItemModel::SetTitle(const std::string& title) { - if (title_ == title) +void AppListItemModel::SetTitleAndFullName(const std::string& title, + const std::string& full_name) { + if (title_ == title && full_name_ == full_name) return; title_ = title; + full_name_ = full_name; FOR_EACH_OBSERVER(AppListItemModelObserver, observers_, ItemTitleChanged()); } diff --git a/chromium/ui/app_list/app_list_item_model.h b/chromium/ui/app_list/app_list_item_model.h index d437564ef75..e9675a83ee1 100644 --- a/chromium/ui/app_list/app_list_item_model.h +++ b/chromium/ui/app_list/app_list_item_model.h @@ -31,8 +31,10 @@ class APP_LIST_EXPORT AppListItemModel { const gfx::ImageSkia& icon() const { return icon_; } bool has_shadow() const { return has_shadow_; } - void SetTitle(const std::string& title); + void SetTitleAndFullName(const std::string& title, + const std::string& full_name); const std::string& title() const { return title_; } + const std::string& full_name() const { return full_name_; } void SetHighlighted(bool highlighted); bool highlighted() const { return highlighted_; } @@ -49,7 +51,8 @@ class APP_LIST_EXPORT AppListItemModel { void AddObserver(AppListItemModelObserver* observer); void RemoveObserver(AppListItemModelObserver* observer); - // Returns the context menu model for this item. + // Returns the context menu model for this item, or NULL if there is currently + // no menu for the item (e.g. during install). // Note the returned menu model is owned by this item. virtual ui::MenuModel* GetContextMenuModel(); @@ -57,6 +60,7 @@ class APP_LIST_EXPORT AppListItemModel { gfx::ImageSkia icon_; bool has_shadow_; std::string title_; + std::string full_name_; bool highlighted_; bool is_installing_; int percent_downloaded_; diff --git a/chromium/ui/app_list/app_list_menu.cc b/chromium/ui/app_list/app_list_menu.cc index 95d6ac38d91..896bcf91965 100644 --- a/chromium/ui/app_list/app_list_menu.cc +++ b/chromium/ui/app_list/app_list_menu.cc @@ -4,6 +4,7 @@ #include "ui/app_list/app_list_menu.h" +#include "grit/ui_resources.h" #include "grit/ui_strings.h" #include "ui/app_list/app_list_view_delegate.h" #include "ui/base/l10n/l10n_util.h" @@ -12,17 +13,40 @@ namespace app_list { -AppListMenu::AppListMenu(AppListViewDelegate* delegate) +AppListMenu::AppListMenu(AppListViewDelegate* delegate, + const AppListModel::Users& users) : menu_model_(this), - delegate_(delegate) { + delegate_(delegate), + users_(users) { InitMenu(); } AppListMenu::~AppListMenu() {} void AppListMenu::InitMenu() { - menu_model_.AddItem(CURRENT_USER, base::string16()); - menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); + // User selector menu section. We don't show the user selector if there is + // only 1 user. + if (users_.size() > 1) { + for (size_t i = 0; i < users_.size(); ++i) { +#if defined(OS_MACOSX) + menu_model_.AddRadioItem(SELECT_PROFILE + i, + users_[i].email.empty() ? users_[i].name + : users_[i].email, + 0 /* group_id */); +#elif defined(OS_WIN) + menu_model_.AddItem(SELECT_PROFILE + i, users_[i].name); + int menu_index = menu_model_.GetIndexOfCommandId(SELECT_PROFILE + i); + menu_model_.SetSublabel(menu_index, users_[i].email); + // Use custom check mark. + if (users_[i].active) { + ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); + menu_model_.SetIcon(menu_index, gfx::Image(*rb.GetImageSkiaNamed( + IDR_APP_LIST_USER_INDICATOR))); + } +#endif + } + menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); + } menu_model_.AddItem(SHOW_SETTINGS, l10n_util::GetStringUTF16( IDS_APP_LIST_OPEN_SETTINGS)); @@ -35,7 +59,12 @@ void AppListMenu::InitMenu() { } bool AppListMenu::IsCommandIdChecked(int command_id) const { +#if defined(OS_MACOSX) + DCHECK_LT(static_cast<unsigned>(command_id) - SELECT_PROFILE, users_.size()); + return users_[command_id - SELECT_PROFILE].active; +#else return false; +#endif } bool AppListMenu::IsCommandIdEnabled(int command_id) const { @@ -48,9 +77,12 @@ bool AppListMenu::GetAcceleratorForCommandId(int command_id, } void AppListMenu::ExecuteCommand(int command_id, int event_flags) { + if (command_id >= SELECT_PROFILE) { + delegate_->ShowForProfileByPath( + users_[command_id - SELECT_PROFILE].profile_path); + return; + } switch (command_id) { - case CURRENT_USER: - break; // Do nothing. case SHOW_SETTINGS: delegate_->OpenSettings(); break; diff --git a/chromium/ui/app_list/app_list_menu.h b/chromium/ui/app_list/app_list_menu.h index ff4be49e4c5..fa42b936d1d 100644 --- a/chromium/ui/app_list/app_list_menu.h +++ b/chromium/ui/app_list/app_list_menu.h @@ -5,6 +5,7 @@ #ifndef UI_APP_LIST_APP_LIST_MENU_H_ #define UI_APP_LIST_APP_LIST_MENU_H_ +#include "ui/app_list/app_list_model.h" #include "ui/base/models/simple_menu_model.h" namespace app_list { @@ -17,13 +18,17 @@ class AppListViewDelegate; class AppListMenu : public ui::SimpleMenuModel::Delegate { public: enum AppListMenuCommands { - CURRENT_USER, SHOW_SETTINGS, SHOW_HELP, SHOW_FEEDBACK, + // |SELECT_PROFILE| must remain the last enum because values greater than + // |SELECT_PROFILE| are used to indicate a profile index. + SELECT_PROFILE, }; - explicit AppListMenu(AppListViewDelegate* delegate); + AppListMenu( + AppListViewDelegate* delegate, + const AppListModel::Users& users); virtual ~AppListMenu(); ui::SimpleMenuModel* menu_model() { return &menu_model_; } @@ -40,6 +45,7 @@ class AppListMenu : public ui::SimpleMenuModel::Delegate { ui::SimpleMenuModel menu_model_; AppListViewDelegate* delegate_; + AppListModel::Users users_; DISALLOW_COPY_AND_ASSIGN(AppListMenu); }; diff --git a/chromium/ui/app_list/app_list_model.cc b/chromium/ui/app_list/app_list_model.cc index 4f473efbc36..d8e3c8bc016 100644 --- a/chromium/ui/app_list/app_list_model.cc +++ b/chromium/ui/app_list/app_list_model.cc @@ -11,10 +11,15 @@ namespace app_list { +AppListModel::User::User() : active(false) {} + +AppListModel::User::~User() {} + AppListModel::AppListModel() : apps_(new Apps), search_box_(new SearchBoxModel), results_(new SearchResults), + signed_in_(false), status_(STATUS_NORMAL) { } @@ -39,4 +44,21 @@ void AppListModel::SetStatus(Status status) { OnAppListModelStatusChanged()); } +void AppListModel::SetUsers(const Users& users) { + users_ = users; + FOR_EACH_OBSERVER(AppListModelObserver, + observers_, + OnAppListModelUsersChanged()); +} + +void AppListModel::SetSignedIn(bool signed_in) { + if (signed_in_ == signed_in) + return; + + signed_in_ = signed_in; + FOR_EACH_OBSERVER(AppListModelObserver, + observers_, + OnAppListModelSigninStatusChanged()); +} + } // namespace app_list diff --git a/chromium/ui/app_list/app_list_model.h b/chromium/ui/app_list/app_list_model.h index 4c46a012329..1145a3683fb 100644 --- a/chromium/ui/app_list/app_list_model.h +++ b/chromium/ui/app_list/app_list_model.h @@ -5,9 +5,13 @@ #ifndef UI_APP_LIST_APP_LIST_MODEL_H_ #define UI_APP_LIST_APP_LIST_MODEL_H_ +#include <vector> + #include "base/basictypes.h" +#include "base/files/file_path.h" #include "base/memory/scoped_ptr.h" #include "base/observer_list.h" +#include "base/strings/string16.h" #include "ui/app_list/app_list_export.h" #include "ui/base/models/list_model.h" @@ -24,6 +28,24 @@ class SearchResult; // the model for SearchBoxView. SearchResults owns a list of SearchResult. class APP_LIST_EXPORT AppListModel { public: + // A user of the app list. + struct APP_LIST_EXPORT User { + User(); + ~User(); + + // Whether or not this user is the current user of the app list. + bool active; + + // The name of this user. + base::string16 name; + + // The email address of this user. + base::string16 email; + + // The path to this user's profile directory. + base::FilePath profile_path; + }; + enum Status { STATUS_NORMAL, STATUS_SYNCING, // Syncing apps or installing synced apps. @@ -31,6 +53,7 @@ class APP_LIST_EXPORT AppListModel { typedef ui::ListModel<AppListItemModel> Apps; typedef ui::ListModel<SearchResult> SearchResults; + typedef std::vector<User> Users; AppListModel(); ~AppListModel(); @@ -39,11 +62,18 @@ class APP_LIST_EXPORT AppListModel { void RemoveObserver(AppListModelObserver* observer); void SetStatus(Status status); + void SetUsers(const Users& profile_menu_items); + void SetSignedIn(bool signed_in); Apps* apps() { return apps_.get(); } SearchBoxModel* search_box() { return search_box_.get(); } SearchResults* results() { return results_.get(); } Status status() const { return status_; } + bool signed_in() const { return signed_in_; } + + const Users& users() const { + return users_; + } private: scoped_ptr<Apps> apps_; @@ -51,6 +81,9 @@ class APP_LIST_EXPORT AppListModel { scoped_ptr<SearchBoxModel> search_box_; scoped_ptr<SearchResults> results_; + Users users_; + + bool signed_in_; Status status_; ObserverList<AppListModelObserver> observers_; diff --git a/chromium/ui/app_list/app_list_model_observer.h b/chromium/ui/app_list/app_list_model_observer.h index c843894c12f..e409fa7fb43 100644 --- a/chromium/ui/app_list/app_list_model_observer.h +++ b/chromium/ui/app_list/app_list_model_observer.h @@ -12,7 +12,13 @@ namespace app_list { class APP_LIST_EXPORT AppListModelObserver { public: // Invoked when AppListModel's status has changed. - virtual void OnAppListModelStatusChanged() = 0; + virtual void OnAppListModelStatusChanged() {} + + // Invoked when AppListModel's profile menu items have changed. + virtual void OnAppListModelUsersChanged() {} + + // Invoked when AppListModel's current user's signin status has changed. + virtual void OnAppListModelSigninStatusChanged() {} protected: virtual ~AppListModelObserver() {} diff --git a/chromium/ui/app_list/app_list_view_delegate.h b/chromium/ui/app_list/app_list_view_delegate.h index bd7e3d3837f..3979e63684d 100644 --- a/chromium/ui/app_list/app_list_view_delegate.h +++ b/chromium/ui/app_list/app_list_view_delegate.h @@ -29,9 +29,15 @@ class APP_LIST_EXPORT AppListViewDelegate { // AppListView owns the delegate. virtual ~AppListViewDelegate() {} - // Invoked to set the model that AppListView uses. + // Sets the delegate to use the profile at |profile_path|. This is currently + // only used by non-Ash Windows. + virtual void SetProfileByPath(const base::FilePath& profile_path) = 0; + + // Invoked to initialize the model that AppListView uses. This binds the given + // model to this AppListViewDelegate and makes the AppListViewDelegate + // responsible for updating the model. // Note that AppListView owns the model. - virtual void SetModel(AppListModel* model) = 0; + virtual void InitModel(AppListModel* model) = 0; // Gets the SigninDelegate for the app list. Owned by the AppListViewDelegate. virtual SigninDelegate* GetSigninDelegate() = 0; @@ -70,18 +76,9 @@ class APP_LIST_EXPORT AppListViewDelegate { // Invoked when the app list is closing. virtual void ViewClosing() = 0; - // Invoked when the app list's activated state changes. - virtual void ViewActivationChanged(bool active) = 0; - // Returns the icon to be displayed in the window and taskbar. virtual gfx::ImageSkia GetWindowIcon() = 0; - // Returns the name of the current user. - virtual base::string16 GetCurrentUserName() = 0; - - // Returns the email of the current user. - virtual base::string16 GetCurrentUserEmail() = 0; - // Open the settings UI. virtual void OpenSettings() = 0; @@ -90,6 +87,9 @@ class APP_LIST_EXPORT AppListViewDelegate { // Open the feedback UI. virtual void OpenFeedback() = 0; + + // Shows the app list for the profile specified by |profile_path|. + virtual void ShowForProfileByPath(const base::FilePath& profile_path) = 0; }; } // namespace app_list diff --git a/chromium/ui/app_list/cocoa/app_list_view_controller.h b/chromium/ui/app_list/cocoa/app_list_view_controller.h index 2815e0a223a..b993a67683b 100644 --- a/chromium/ui/app_list/cocoa/app_list_view_controller.h +++ b/chromium/ui/app_list/cocoa/app_list_view_controller.h @@ -17,7 +17,7 @@ namespace app_list { class AppListViewDelegate; class AppListModel; -class SigninDelegateObserverBridge; +class AppListModelObserverBridge; } @class AppListPagerView; @@ -46,7 +46,8 @@ APP_LIST_EXPORT base::scoped_nsobject<NSView> contentsView_; scoped_ptr<app_list::AppListViewDelegate> delegate_; - scoped_ptr<app_list::SigninDelegateObserverBridge> signin_observer_bridge_; + scoped_ptr<app_list::AppListModelObserverBridge> + app_list_model_observer_bridge_; BOOL showingSearchResults_; } diff --git a/chromium/ui/app_list/cocoa/app_list_view_controller.mm b/chromium/ui/app_list/cocoa/app_list_view_controller.mm index e4647216642..5e5eea5c655 100644 --- a/chromium/ui/app_list/cocoa/app_list_view_controller.mm +++ b/chromium/ui/app_list/cocoa/app_list_view_controller.mm @@ -6,12 +6,13 @@ #include "base/mac/foundation_util.h" #include "base/strings/string_util.h" +#include "base/strings/sys_string_conversions.h" #include "skia/ext/skia_utils_mac.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_model.h" +#include "ui/app_list/app_list_model_observer.h" #include "ui/app_list/app_list_view_delegate.h" #include "ui/app_list/signin_delegate.h" -#include "ui/app_list/signin_delegate_observer.h" #import "ui/app_list/cocoa/app_list_pager_view.h" #import "ui/app_list/cocoa/apps_grid_controller.h" #import "ui/app_list/cocoa/signin_view_controller.h" @@ -75,34 +76,44 @@ const NSTimeInterval kResultsAnimationDuration = 0.2; - (void)loadAndSetView; - (void)revealSearchResults:(BOOL)show; -- (app_list::SigninDelegate*)signinDelegate; @end namespace app_list { -class SigninDelegateObserverBridge : public SigninDelegateObserver { +class AppListModelObserverBridge : public AppListModelObserver { public: - SigninDelegateObserverBridge(AppListViewController* parent) - : parent_(parent) { - [parent_ signinDelegate]->AddObserver(this); - } - - virtual ~SigninDelegateObserverBridge() { - [parent_ signinDelegate]->RemoveObserver(this); - } + AppListModelObserverBridge(AppListViewController* parent); + virtual ~AppListModelObserverBridge(); private: - // SigninDelegateObserver override: - virtual void OnSigninSuccess() OVERRIDE { - [parent_ onSigninStatusChanged]; - } + // Overridden from app_list::AppListModelObserver: + virtual void OnAppListModelUsersChanged() OVERRIDE; + virtual void OnAppListModelSigninStatusChanged() OVERRIDE; AppListViewController* parent_; // Weak. Owns us. - DISALLOW_COPY_AND_ASSIGN(SigninDelegateObserverBridge); + DISALLOW_COPY_AND_ASSIGN(AppListModelObserverBridge); }; +AppListModelObserverBridge::AppListModelObserverBridge( + AppListViewController* parent) + : parent_(parent) { + [[parent_ appsGridController] model]->AddObserver(this); +} + +AppListModelObserverBridge::~AppListModelObserverBridge() { + [[parent_ appsGridController] model]->RemoveObserver(this); +} + +void AppListModelObserverBridge::OnAppListModelUsersChanged() { + [parent_ onSigninStatusChanged]; +} + +void AppListModelObserverBridge::OnAppListModelSigninStatusChanged() { + [parent_ onSigninStatusChanged]; +} + } // namespace app_list @implementation AppListViewController @@ -148,7 +159,7 @@ class SigninDelegateObserverBridge : public SigninDelegateObserver { withTestModel:(scoped_ptr<app_list::AppListModel>)newModel { if (delegate_) { // First clean up, in reverse order. - signin_observer_bridge_.reset(); + app_list_model_observer_bridge_.reset(); [appsSearchResultsController_ setDelegate:nil]; [appsSearchBoxController_ setDelegate:nil]; } @@ -158,6 +169,8 @@ class SigninDelegateObserverBridge : public SigninDelegateObserver { [appsGridController_ setModel:newModel.Pass()]; [appsSearchBoxController_ setDelegate:self]; [appsSearchResultsController_ setDelegate:self]; + app_list_model_observer_bridge_.reset( + new app_list::AppListModelObserverBridge(self)); [self onSigninStatusChanged]; } @@ -316,14 +329,21 @@ class SigninDelegateObserverBridge : public SigninDelegateObserver { [appsSearchBoxController_ clearSearch]; } +- (void)redoSearch { + [self modelTextDidChange]; +} + - (void)onSigninStatusChanged { [appsSearchBoxController_ rebuildMenu]; - app_list::SigninDelegate* signinDelegate = [self signinDelegate]; - BOOL needsSignin = signinDelegate && signinDelegate->NeedSignin(); - if (!needsSignin) { - [[signinViewController_ view] removeFromSuperview]; - signin_observer_bridge_.reset(); - signinViewController_.reset(); + app_list::SigninDelegate* signinDelegate = + delegate_ ? delegate_->GetSigninDelegate() : NULL; + BOOL show_signin_view = + signinDelegate && ![appsGridController_ model]->signed_in(); + + [[signinViewController_ view] removeFromSuperview]; + signinViewController_.reset(); + + if (!show_signin_view) { [backgroundView_ setHidden:NO]; return; } @@ -333,13 +353,7 @@ class SigninDelegateObserverBridge : public SigninDelegateObserver { [[SigninViewController alloc] initWithFrame:[backgroundView_ frame] cornerRadius:kBubbleCornerRadius delegate:signinDelegate]); - signin_observer_bridge_.reset( - new app_list::SigninDelegateObserverBridge(self)); [[self view] addSubview:[signinViewController_ view]]; } -- (app_list::SigninDelegate*)signinDelegate { - return delegate_ ? delegate_->GetSigninDelegate() : NULL; -} - @end diff --git a/chromium/ui/app_list/cocoa/app_list_view_controller_unittest.mm b/chromium/ui/app_list/cocoa/app_list_view_controller_unittest.mm index 70769aba759..2836ceb2399 100644 --- a/chromium/ui/app_list/cocoa/app_list_view_controller_unittest.mm +++ b/chromium/ui/app_list/cocoa/app_list_view_controller_unittest.mm @@ -67,22 +67,6 @@ class AppListViewControllerTest : public AppsGridControllerTestHelper, DISALLOW_COPY_AND_ASSIGN(AppListViewControllerTest); }; -// Helper class allowing NeedSignin() to return true during SetUp(), to test an -// initial state where signin is required, and the regular view starts hidden. -class AppListViewControllerSigninTest : public AppListViewControllerTest { - public: - AppListViewControllerSigninTest() : needs_signin_(true) {} - - // SigninDelegate override: - virtual bool NeedSignin() OVERRIDE { return needs_signin_; } - - protected: - bool needs_signin_; - - private: - DISALLOW_COPY_AND_ASSIGN(AppListViewControllerSigninTest); -}; - TEST_VIEW(AppListViewControllerTest, [app_list_view_controller_ view]); // Test that adding and removing pages updates the pager. @@ -136,13 +120,16 @@ TEST_F(AppListViewControllerTest, SignedIn) { } // Test the view when signin is required. -TEST_F(AppListViewControllerSigninTest, NeedsSignin) { +TEST_F(AppListViewControllerTest, NeedsSignin) { + // Begin the test with a signed out app list. + scoped_ptr<AppListModel> new_model(new AppListModel); + new_model->SetSignedIn(false); + ResetModel(new_model.Pass()); EXPECT_EQ(2u, [[[app_list_view_controller_ view] subviews] count]); EXPECT_TRUE([[app_list_view_controller_ backgroundView] isHidden]); // Simulate signing in, should enter the SignedIn state. - needs_signin_ = false; - NotifySigninSuccess(); + model()->SetSignedIn(true); EXPECT_EQ(1u, [[[app_list_view_controller_ view] subviews] count]); EXPECT_FALSE([[app_list_view_controller_ backgroundView] isHidden]); } diff --git a/chromium/ui/app_list/cocoa/apps_grid_controller.mm b/chromium/ui/app_list/cocoa/apps_grid_controller.mm index d32a7913397..851653e6837 100644 --- a/chromium/ui/app_list/cocoa/apps_grid_controller.mm +++ b/chromium/ui/app_list/cocoa/apps_grid_controller.mm @@ -213,7 +213,7 @@ class AppsGridDelegateBridge : public ui::ListModelObserver { scoped_ptr<app_list::AppListModel> newModel(new app_list::AppListModel); delegate_ = newDelegate; if (delegate_) - delegate_->SetModel(newModel.get()); // Populates items. + delegate_->InitModel(newModel.get()); // Populates items. [self setModel:newModel.Pass()]; } @@ -546,9 +546,6 @@ class AppsGridDelegateBridge : public ui::ListModelObserver { } [self updatePages:start]; - - for (size_t i = start; i < start + count; ++i) - [[self itemAtIndex:i] onInitialModelBuilt]; } - (void)listItemsRemoved:(size_t)start diff --git a/chromium/ui/app_list/cocoa/apps_grid_controller_unittest.mm b/chromium/ui/app_list/cocoa/apps_grid_controller_unittest.mm index 1e331bc6dfb..d4f73d68196 100644 --- a/chromium/ui/app_list/cocoa/apps_grid_controller_unittest.mm +++ b/chromium/ui/app_list/cocoa/apps_grid_controller_unittest.mm @@ -122,17 +122,27 @@ class AppsGridControllerTest : public AppsGridControllerTestHelper { class AppListItemWithMenu : public AppListItemModel { public: - AppListItemWithMenu(const std::string& title) : menu_model_(NULL) { - SetTitle(title); + AppListItemWithMenu(const std::string& title) + : menu_model_(NULL), + menu_ready_(true) { + SetTitleAndFullName(title, title); menu_model_.AddItem(0, UTF8ToUTF16("Menu For: " + title)); } + void SetMenuReadyForTesting(bool ready) { + menu_ready_ = ready; + } + virtual ui::MenuModel* GetContextMenuModel() OVERRIDE { + if (!menu_ready_) + return NULL; + return &menu_model_; } private: ui::SimpleMenuModel menu_model_; + bool menu_ready_; DISALLOW_COPY_AND_ASSIGN(AppListItemWithMenu); }; @@ -424,7 +434,7 @@ TEST_F(AppsGridControllerTest, ModelUpdates) { // Update the title via the ItemModelObserver. app_list::AppListItemModel* item_model = model()->apps()->GetItemAt(2); - item_model->SetTitle("UpdatedItem"); + item_model->SetTitleAndFullName("UpdatedItem", "UpdatedItem"); EXPECT_NSEQ(@"UpdatedItem", [button title]); EXPECT_EQ(std::string("|Item 0,Item 1,UpdatedItem|"), GetViewContent()); @@ -457,7 +467,7 @@ TEST_F(AppsGridControllerTest, ModelUpdates) { EXPECT_EQ(std::string("|Item 0,Item 2|"), GetViewContent()); // Test inserting in the middle. - model()->apps()->AddAt(1, model()->CreateItem("Item One")); + model()->apps()->AddAt(1, model()->CreateItem("Item One", "Item One")); EXPECT_EQ(3u, [apps_grid_controller_ itemCount]); EXPECT_EQ(std::string("|Item 0,Item One,Item 2|"), GetViewContent()); @@ -891,8 +901,9 @@ TEST_F(AppsGridControllerTest, ScrollingWhileDragging) { } TEST_F(AppsGridControllerTest, ContextMenus) { + AppListItemWithMenu* item_two_model = new AppListItemWithMenu("Item Two"); model()->apps()->AddAt(0, new AppListItemWithMenu("Item One")); - model()->apps()->AddAt(1, new AppListItemWithMenu("Item Two")); + model()->apps()->AddAt(1, item_two_model); EXPECT_EQ(2u, [apps_grid_controller_ itemCount]); NSCollectionView* page = [apps_grid_controller_ collectionViewAtPageIndex:0]; @@ -903,55 +914,16 @@ TEST_F(AppsGridControllerTest, ContextMenus) { EXPECT_EQ(1, [menu numberOfItems]); EXPECT_NSEQ(@"Menu For: Item One", [[menu itemAtIndex:0] title]); + // Test a context menu request while the item is still installing. + item_two_model->SetMenuReadyForTesting(false); + menu = [page menuForEvent:mouse_at_cell_1]; + EXPECT_EQ(nil, menu); + + item_two_model->SetMenuReadyForTesting(true); menu = [page menuForEvent:mouse_at_cell_1]; EXPECT_EQ(1, [menu numberOfItems]); EXPECT_NSEQ(@"Menu For: Item Two", [[menu itemAtIndex:0] title]); } -TEST_F(AppsGridControllerTest, HighlightedOnFirstShow) { - scoped_ptr<AppListTestModel> test_model(new AppListTestModel); - test_model->PopulateApps(kItemsPerPage * 3); - - // Manipulate the second item on the second page. - const size_t kTestItemIndex = kItemsPerPage + 1; - - // When shown for the first time during an in-progress install, item should be - // visible, but not selected. - AppListItemModel* test_item = test_model->apps()->GetItemAt(kTestItemIndex); - test_item->SetHighlighted(true); - test_item->SetIsInstalling(true); - EXPECT_EQ(0u, [apps_grid_controller_ visiblePage]); - ResetModel(test_model.PassAs<AppListModel>()); - EXPECT_EQ(3u, [apps_grid_controller_ pageCount]); - EXPECT_EQ(1u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(NSNotFound, [apps_grid_controller_ selectedItemIndex]); - - // Updating download progress should add a progress bar lazily. - NSView* containerView = [GetItemViewAt(kTestItemIndex) superview]; - EXPECT_EQ(1u, [[containerView subviews] count]); - test_item->SetPercentDownloaded(50); - EXPECT_EQ(2u, [[containerView subviews] count]); - - // Completing install should remove the progress bar, and select the item. - test_item->SetIsInstalling(false); - EXPECT_EQ(1u, [[containerView subviews] count]); - EXPECT_EQ(kTestItemIndex, [apps_grid_controller_ selectedItemIndex]); - - // Reset to unconstructed state. - ResetModel(scoped_ptr<AppListModel>()); - EXPECT_EQ(0u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(1u, [apps_grid_controller_ pageCount]); - EXPECT_EQ(NSNotFound, [apps_grid_controller_ selectedItemIndex]); - - // If shown after install completes, item should also be selected. - test_model.reset(new AppListTestModel); - test_model->PopulateApps(kItemsPerPage * 3); - test_model->apps()->GetItemAt(kTestItemIndex)->SetHighlighted(true); - ResetModel(test_model.PassAs<AppListModel>()); - EXPECT_EQ(3u, [apps_grid_controller_ pageCount]); - EXPECT_EQ(1u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(kTestItemIndex, [apps_grid_controller_ selectedItemIndex]); -} - } // namespace test } // namespace app_list diff --git a/chromium/ui/app_list/cocoa/apps_grid_view_item.h b/chromium/ui/app_list/cocoa/apps_grid_view_item.h index d968e0cb5cd..b42eec18761 100644 --- a/chromium/ui/app_list/cocoa/apps_grid_view_item.h +++ b/chromium/ui/app_list/cocoa/apps_grid_view_item.h @@ -50,10 +50,6 @@ APP_LIST_EXPORT // the initial snapshot are restored. - (NSBitmapImageRep*)dragRepresentationForRestore:(BOOL)isRestore; -// Called the first time an item is added to the grid view, once the grid view -// is consistent with items being added at the same time. -- (void)onInitialModelBuilt; - @end #endif // UI_APP_LIST_COCOA_APPS_GRID_VIEW_ITEM_H_ diff --git a/chromium/ui/app_list/cocoa/apps_grid_view_item.mm b/chromium/ui/app_list/cocoa/apps_grid_view_item.mm index 34fe975ebca..b6e4fb53a27 100644 --- a/chromium/ui/app_list/cocoa/apps_grid_view_item.mm +++ b/chromium/ui/app_list/cocoa/apps_grid_view_item.mm @@ -99,8 +99,12 @@ ItemModelObserverBridge::~ItemModelObserverBridge() { NSMenu* ItemModelObserverBridge::GetContextMenu() { if (!context_menu_controller_) { + ui::MenuModel* menu_model = model_->GetContextMenuModel(); + if (!menu_model) + return nil; + context_menu_controller_.reset( - [[MenuController alloc] initWithModel:model_->GetContextMenuModel() + [[MenuController alloc] initWithModel:menu_model useWithPopUpButtonCell:NO]); } return [context_menu_controller_ menu]; @@ -255,6 +259,18 @@ void ItemModelObserverBridge::ItemPercentDownloadedChanged() { [[NSAttributedString alloc] initWithString:buttonTitle attributes:titleAttributes]); [[self button] setAttributedTitle:attributedTitle]; + + // If the app does not specify a distinct short name manifest property, check + // whether the title would be truncted in the NSButton. If it would be + // truncated, add a tooltip showing the full name. + NSRect titleRect = + [[[self button] cell] titleRectForBounds:[[self button] bounds]]; + if ([self model]->title() == [self model]->full_name() && + [attributedTitle size].width < NSWidth(titleRect)) { + [[self view] removeAllToolTips]; + } else { + [[self view] setToolTip:base::SysUTF8ToNSString([self model]->full_name())]; + } } - (void)updateButtonImage { @@ -271,6 +287,7 @@ void ItemModelObserverBridge::ItemPercentDownloadedChanged() { } - (void)setModel:(app_list::AppListItemModel*)itemModel { + [trackingArea_.get() clearOwner]; if (!itemModel) { observerBridge_.reset(); return; @@ -335,14 +352,6 @@ void ItemModelObserverBridge::ItemPercentDownloadedChanged() { return imageRep; } -- (void)onInitialModelBuilt { - if ([self model]->highlighted()) { - [self ensureVisible]; - if (![self model]->is_installing()) - [self setSelected:YES]; - } -} - - (void)ensureVisible { NSCollectionView* collectionView = [self collectionView]; AppsGridController* gridController = diff --git a/chromium/ui/app_list/cocoa/apps_search_box_controller.h b/chromium/ui/app_list/cocoa/apps_search_box_controller.h index d28c67a62e8..b8a86e57f7b 100644 --- a/chromium/ui/app_list/cocoa/apps_search_box_controller.h +++ b/chromium/ui/app_list/cocoa/apps_search_box_controller.h @@ -13,6 +13,7 @@ namespace app_list { class AppListMenu; +class AppListModel; class AppListViewDelegate; class SearchBoxModel; class SearchBoxModelObserverBridge; @@ -26,6 +27,7 @@ class SearchBoxModelObserverBridge; - (app_list::AppListViewDelegate*)appListDelegate; - (app_list::SearchBoxModel*)searchBoxModel; +- (app_list::AppListModel*)appListModel; - (void)modelTextDidChange; @end diff --git a/chromium/ui/app_list/cocoa/apps_search_box_controller.mm b/chromium/ui/app_list/cocoa/apps_search_box_controller.mm index 4f02a20c56b..2fa9928b207 100644 --- a/chromium/ui/app_list/cocoa/apps_search_box_controller.mm +++ b/chromium/ui/app_list/cocoa/apps_search_box_controller.mm @@ -10,7 +10,7 @@ #include "grit/ui_resources.h" #import "third_party/GTM/AppKit/GTMNSBezierPath+RoundRect.h" #include "ui/app_list/app_list_menu.h" -#import "ui/app_list/cocoa/current_user_menu_item_view.h" +#include "ui/app_list/app_list_model.h" #include "ui/app_list/search_box_model.h" #include "ui/app_list/search_box_model_observer.h" #import "ui/base/cocoa/controls/hover_image_menu_button.h" @@ -110,6 +110,7 @@ void SearchBoxModelObserverBridge::TextChanged() { // it is changed in tests to establish a particular state. [[parent_ searchTextField] setStringValue:base::SysUTF16ToNSString(GetModel()->text())]; + [[parent_ delegate] modelTextDidChange]; } } // namespace app_list @@ -158,6 +159,10 @@ void SearchBoxModelObserverBridge::TextChanged() { if (![delegate_ appListDelegate]) return; + [menuController_ setModel:NULL]; + appListMenu_.reset( + new app_list::AppListMenu([delegate_ appListDelegate], + [delegate_ appListModel]->users())); menuController_.reset([[AppListMenuController alloc] initWithSearchBoxController:self]); [menuButton_ setMenu:[menuController_ menu]]; // Menu will populate here. @@ -173,10 +178,6 @@ void SearchBoxModelObserverBridge::TextChanged() { return; bridge_.reset(new app_list::SearchBoxModelObserverBridge(self)); - if (![delegate_ appListDelegate]) - return; - - appListMenu_.reset(new app_list::AppListMenu([delegate_ appListDelegate])); [self rebuildMenu]; } @@ -371,20 +372,6 @@ void SearchBoxModelObserverBridge::TextChanged() { return self; } -- (void)addItemToMenu:(NSMenu*)menu - atIndex:(NSInteger)index - fromModel:(ui::MenuModel*)model { - [super addItemToMenu:menu - atIndex:index - fromModel:model]; - if (model->GetCommandIdAt(index) != app_list::AppListMenu::CURRENT_USER) - return; - - base::scoped_nsobject<NSView> customItemView([[CurrentUserMenuItemView alloc] - initWithDelegate:[[searchBoxController_ delegate] appListDelegate]]); - [[menu itemAtIndex:index] setView:customItemView]; -} - - (NSRect)confinementRectForMenu:(NSMenu*)menu onScreen:(NSScreen*)screen { NSPopUpButton* menuButton = [searchBoxController_ menuControl]; diff --git a/chromium/ui/app_list/cocoa/apps_search_box_controller_unittest.mm b/chromium/ui/app_list/cocoa/apps_search_box_controller_unittest.mm index d702549e7a1..d410380c856 100644 --- a/chromium/ui/app_list/cocoa/apps_search_box_controller_unittest.mm +++ b/chromium/ui/app_list/cocoa/apps_search_box_controller_unittest.mm @@ -9,16 +9,18 @@ #include "base/strings/utf_string_conversions.h" #import "testing/gtest_mac.h" #include "ui/app_list/app_list_menu.h" -#import "ui/app_list/cocoa/current_user_menu_item_view.h" +#include "ui/app_list/app_list_model_observer.h" #include "ui/app_list/search_box_model.h" #include "ui/app_list/test/app_list_test_model.h" #include "ui/app_list/test/app_list_test_view_delegate.h" +#import "ui/base/cocoa/menu_controller.h" #import "ui/base/test/ui_cocoa_test_helper.h" @interface TestAppsSearchBoxDelegate : NSObject<AppsSearchBoxDelegate> { @private app_list::SearchBoxModel searchBoxModel_; app_list::test::AppListTestViewDelegate appListDelegate_; + app_list::test::AppListTestModel appListModel_; int textChangeCount_; } @@ -30,6 +32,18 @@ @synthesize textChangeCount = textChangeCount_; +- (id)init { + if ((self = [super init])) { + app_list::AppListModel::Users users(2); + users[0].name = ASCIIToUTF16("user1"); + users[1].name = ASCIIToUTF16("user2"); + users[1].email = ASCIIToUTF16("user2@chromium.org"); + users[1].active = true; + appListModel_.SetUsers(users); + } + return self; +} + - (app_list::SearchBoxModel*)searchBoxModel { return &searchBoxModel_; } @@ -52,12 +66,17 @@ return 3; } +- (app_list::AppListModel*)appListModel { + return &appListModel_; +} + @end namespace app_list { namespace test { -class AppsSearchBoxControllerTest : public ui::CocoaTest { +class AppsSearchBoxControllerTest : public ui::CocoaTest, + public AppListModelObserver { public: AppsSearchBoxControllerTest() { Init(); @@ -69,12 +88,14 @@ class AppsSearchBoxControllerTest : public ui::CocoaTest { NSMakeRect(0, 0, 400, 100)]); delegate_.reset([[TestAppsSearchBoxDelegate alloc] init]); [apps_search_box_controller_ setDelegate:delegate_]; + [delegate_ appListModel]->AddObserver(this); ui::CocoaTest::SetUp(); [[test_window() contentView] addSubview:[apps_search_box_controller_ view]]; } virtual void TearDown() OVERRIDE { + [delegate_ appListModel]->RemoveObserver(this); [apps_search_box_controller_ setDelegate:nil]; ui::CocoaTest::TearDown(); } @@ -87,6 +108,13 @@ class AppsSearchBoxControllerTest : public ui::CocoaTest { } protected: + // Overridden from app_list::AppListModelObserver: + virtual void OnAppListModelUsersChanged() OVERRIDE { + [apps_search_box_controller_ rebuildMenu]; + } + + virtual void OnAppListModelSigninStatusChanged() OVERRIDE {} + base::scoped_nsobject<TestAppsSearchBoxDelegate> delegate_; base::scoped_nsobject<AppsSearchBoxController> apps_search_box_controller_; @@ -109,28 +137,57 @@ TEST_F(AppsSearchBoxControllerTest, SearchBoxModel) { model->SetText(search_text); EXPECT_NSEQ(base::SysUTF16ToNSString(search_text), [[apps_search_box_controller_ searchTextField] stringValue]); - // Updates coming via the model should not notify the delegate. - EXPECT_EQ(0, [delegate_ textChangeCount]); + // Updates coming via the model should notify the delegate. + EXPECT_EQ(1, [delegate_ textChangeCount]); // Updates from the view should update the model and notify the delegate. [apps_search_box_controller_ clearSearch]; EXPECT_EQ(base::string16(), model->text()); EXPECT_NSEQ([NSString string], [[apps_search_box_controller_ searchTextField] stringValue]); - EXPECT_EQ(1, [delegate_ textChangeCount]); + EXPECT_EQ(2, [delegate_ textChangeCount]); - // Test pressing escape clears the search. + // Test pressing escape clears the search. First add some text. model->SetText(search_text); + EXPECT_EQ(3, [delegate_ textChangeCount]); + EXPECT_NSEQ(base::SysUTF16ToNSString(search_text), [[apps_search_box_controller_ searchTextField] stringValue]); SimulateKeyAction(@selector(complete:)); EXPECT_NSEQ([NSString string], [[apps_search_box_controller_ searchTextField] stringValue]); - EXPECT_EQ(2, [delegate_ textChangeCount]); + EXPECT_EQ(4, [delegate_ textChangeCount]); } -// Test the popup menu items. +// Test the popup menu items when there is only one user.. +TEST_F(AppsSearchBoxControllerTest, SearchBoxMenuSingleUser) { + // Set a single user. We need to set the delegate again because the + // AppListModel observer isn't hooked up in these tests. + [delegate_ appListModel]->SetUsers(app_list::AppListModel::Users(1)); + [apps_search_box_controller_ setDelegate:delegate_]; + + NSPopUpButton* menu_control = [apps_search_box_controller_ menuControl]; + EXPECT_TRUE([apps_search_box_controller_ appListMenu]); + ui::MenuModel* menu_model + = [apps_search_box_controller_ appListMenu]->menu_model(); + // Add one to the item count to account for the blank, first item that Cocoa + // has in its popup menus. + EXPECT_EQ(menu_model->GetItemCount() + 1, + [[menu_control menu] numberOfItems]); + + // All command ids should be less than |SELECT_PROFILE| as no user menu items + // are being shown. + for (int i = 0; i < menu_model->GetItemCount(); ++i) + EXPECT_LT(menu_model->GetCommandIdAt(i), AppListMenu::SELECT_PROFILE); + + // The number of items should match the index that starts profile items. + EXPECT_EQ(AppListMenu::SELECT_PROFILE, menu_model->GetItemCount()); +} + +// Test the popup menu items for the multi-profile case. TEST_F(AppsSearchBoxControllerTest, SearchBoxMenu) { + const app_list::AppListModel::Users& users = + [delegate_ appListModel]->users(); NSPopUpButton* menu_control = [apps_search_box_controller_ menuControl]; EXPECT_TRUE([apps_search_box_controller_ appListMenu]); ui::MenuModel* menu_model @@ -140,14 +197,31 @@ TEST_F(AppsSearchBoxControllerTest, SearchBoxMenu) { EXPECT_EQ(menu_model->GetItemCount() + 1, [[menu_control menu] numberOfItems]); - // The CURRENT_USER item should contain our custom view. ui::MenuModel* found_menu_model = menu_model; int index; + MenuController* controller = [[menu_control menu] delegate]; + + // The first user item is an unchecked label. + EXPECT_TRUE(ui::MenuModel::GetModelAndIndexForCommandId( + AppListMenu::SELECT_PROFILE, &menu_model, &index)); + EXPECT_EQ(found_menu_model, menu_model); + NSMenuItem* unchecked_user_item = [[menu_control menu] itemAtIndex:index + 1]; + [controller validateUserInterfaceItem:unchecked_user_item]; + // The profile name should be shown if there is no email available. + EXPECT_NSEQ(base::SysUTF16ToNSString(users[0].name), + [unchecked_user_item title]); + EXPECT_EQ(NSOffState, [unchecked_user_item state]); + + // The second user item is a checked label because it is the active profile. EXPECT_TRUE(ui::MenuModel::GetModelAndIndexForCommandId( - AppListMenu::CURRENT_USER, &menu_model, &index)); + AppListMenu::SELECT_PROFILE + 1, &menu_model, &index)); EXPECT_EQ(found_menu_model, menu_model); - NSMenuItem* current_user_item = [[menu_control menu] itemAtIndex:index + 1]; - EXPECT_TRUE([current_user_item view]); + NSMenuItem* checked_user_item = [[menu_control menu] itemAtIndex:index + 1]; + [controller validateUserInterfaceItem:checked_user_item]; + // The email is shown when available. + EXPECT_NSEQ(base::SysUTF16ToNSString(users[1].email), + [checked_user_item title]); + EXPECT_EQ(NSOnState, [checked_user_item state]); // A regular item should have just the label. EXPECT_TRUE(ui::MenuModel::GetModelAndIndexForCommandId( @@ -159,30 +233,33 @@ TEST_F(AppsSearchBoxControllerTest, SearchBoxMenu) { [settings_item title]); } -// Test initialization and display of the custom menu item that shows the -// currently signed-in user. This is a non-interactive view. -class AppsSearchBoxCustomMenuItemTest : public ui::CocoaTest { - public: - AppsSearchBoxCustomMenuItemTest() { - Init(); - } - - virtual void SetUp() OVERRIDE { - scoped_ptr<AppListViewDelegate> delegate(new AppListTestViewDelegate); - current_user_menu_item_.reset([[[CurrentUserMenuItemView alloc] - initWithDelegate:delegate.get()] retain]); - ui::CocoaTest::SetUp(); - [[test_window() contentView] addSubview:current_user_menu_item_]; - } - - protected: - base::scoped_nsobject<NSView> current_user_menu_item_; - - private: - DISALLOW_COPY_AND_ASSIGN(AppsSearchBoxCustomMenuItemTest); -}; +// Test adding another user, and changing an existing one. +TEST_F(AppsSearchBoxControllerTest, SearchBoxMenuChangingUsers) { + app_list::AppListModel::Users users = [delegate_ appListModel]->users(); + EXPECT_EQ(2u, users.size()); + ui::MenuModel* menu_model + = [apps_search_box_controller_ appListMenu]->menu_model(); + // Adding one to account for the empty item at index 0 in Cocoa popup menus. + int non_user_items = menu_model->GetItemCount() - users.size() + 1; -TEST_VIEW(AppsSearchBoxCustomMenuItemTest, current_user_menu_item_); + NSPopUpButton* menu_control = [apps_search_box_controller_ menuControl]; + EXPECT_EQ(2, [[menu_control menu] numberOfItems] - non_user_items); + EXPECT_NSEQ(base::SysUTF16ToNSString(users[0].name), + [[[menu_control menu] itemAtIndex:1] title]); + + users[0].name = ASCIIToUTF16("renamed user"); + app_list::AppListModel::User new_user; + new_user.name = ASCIIToUTF16("user3"); + users.push_back(new_user); + [delegate_ appListModel]->SetUsers(users); + + // Should now be an extra item, and it should have correct titles. + EXPECT_EQ(3, [[menu_control menu] numberOfItems] - non_user_items); + EXPECT_NSEQ(base::SysUTF16ToNSString(users[0].name), + [[[menu_control menu] itemAtIndex:1] title]); + EXPECT_NSEQ(base::SysUTF16ToNSString(new_user.name), + [[[menu_control menu] itemAtIndex:3] title]); +} } // namespace test } // namespace app_list diff --git a/chromium/ui/app_list/cocoa/apps_search_results_controller.h b/chromium/ui/app_list/cocoa/apps_search_results_controller.h index b69fc511938..52290c7824c 100644 --- a/chromium/ui/app_list/cocoa/apps_search_results_controller.h +++ b/chromium/ui/app_list/cocoa/apps_search_results_controller.h @@ -10,20 +10,21 @@ #include "base/mac/scoped_nsobject.h" #include "base/memory/scoped_ptr.h" #include "ui/app_list/app_list_export.h" +#include "ui/app_list/app_list_model.h" #import "ui/base/cocoa/tracking_area.h" namespace app_list { -class AppListModel; class AppsSearchResultsModelBridge; class SearchResult; } @class AppsSearchResultsCell; -@protocol AppsSearchResultsDelegate +@protocol AppsSearchResultsDelegate<NSObject> - (app_list::AppListModel*)appListModel; - (void)openResult:(app_list::SearchResult*)result; +- (void)redoSearch; @end @@ -40,10 +41,12 @@ APP_LIST_EXPORT NSPoint lastMouseDownInView_; NSInteger hoveredRowIndex_; scoped_ptr<app_list::AppsSearchResultsModelBridge> bridge_; - id<AppsSearchResultsDelegate> delegate_; // Weak. Owns us. + NSObject<AppsSearchResultsDelegate>* delegate_; // Weak. Owns us. } -@property(assign, nonatomic) id<AppsSearchResultsDelegate> delegate; +@property(assign, nonatomic) NSObject<AppsSearchResultsDelegate>* delegate; +@property(readonly, nonatomic) app_list::AppListModel::SearchResults* results; +@property(readonly, nonatomic) NSTableView* tableView; - (id)initWithAppsSearchResultsFrameSize:(NSSize)size; @@ -53,10 +56,4 @@ APP_LIST_EXPORT @end -@interface AppsSearchResultsController (TestingAPI) - -- (NSTableView*)tableView; - -@end - #endif // UI_APP_LIST_COCOA_APPS_SEARCH_RESULTS_CONTROLLER_H_ diff --git a/chromium/ui/app_list/cocoa/apps_search_results_controller.mm b/chromium/ui/app_list/cocoa/apps_search_results_controller.mm index b22d836ab11..314f079e8ad 100644 --- a/chromium/ui/app_list/cocoa/apps_search_results_controller.mm +++ b/chromium/ui/app_list/cocoa/apps_search_results_controller.mm @@ -86,6 +86,15 @@ const NSBackgroundStyle kBackgroundHovered = NSBackgroundStyleRaised; return self; } +- (app_list::AppListModel::SearchResults*)results { + DCHECK([delegate_ appListModel]); + return [delegate_ appListModel]->results(); +} + +- (NSTableView*)tableView { + return tableView_; +} + - (void)setDelegate:(id<AppsSearchResultsDelegate>)newDelegate { bridge_.reset(); delegate_ = newDelegate; @@ -95,8 +104,7 @@ const NSBackgroundStyle kBackgroundHovered = NSBackgroundStyleRaised; return; } - bridge_.reset(new app_list::AppsSearchResultsModelBridge( - appListModel->results(), tableView_)); + bridge_.reset(new app_list::AppsSearchResultsModelBridge(self)); [tableView_ reloadData]; } @@ -116,10 +124,6 @@ const NSBackgroundStyle kBackgroundHovered = NSBackgroundStyleRaised; return NO; } -- (NSTableView*)tableView { - return tableView_; -} - - (void)loadAndSetViewWithResultsFrameSize:(NSSize)size { tableView_.reset( [[AppsSearchResultsTableView alloc] initWithFrame:NSZeroRect]); diff --git a/chromium/ui/app_list/cocoa/apps_search_results_controller_unittest.mm b/chromium/ui/app_list/cocoa/apps_search_results_controller_unittest.mm index 14ce5d26ca5..3645e1e19de 100644 --- a/chromium/ui/app_list/cocoa/apps_search_results_controller_unittest.mm +++ b/chromium/ui/app_list/cocoa/apps_search_results_controller_unittest.mm @@ -5,6 +5,7 @@ #import "ui/app_list/cocoa/apps_search_results_controller.h" #include "base/mac/scoped_nsobject.h" +#include "base/message_loop/message_loop.h" #include "base/strings/stringprintf.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" @@ -20,15 +21,18 @@ @private app_list::test::AppListTestModel appListModel_; app_list::SearchResult* lastOpenedResult_; + int redoSearchCount_; } @property(readonly, nonatomic) app_list::SearchResult* lastOpenedResult; +@property(readonly, nonatomic) int redoSearchCount; @end @implementation TestAppsSearchResultsDelegate @synthesize lastOpenedResult = lastOpenedResult_; +@synthesize redoSearchCount = redoSearchCount_; - (app_list::AppListModel*)appListModel { return &appListModel_; @@ -38,6 +42,10 @@ lastOpenedResult_ = result; } +- (void)redoSearch { + ++redoSearchCount_; +} + @end namespace app_list { @@ -48,19 +56,28 @@ const int kDefaultResultsCount = 3; class SearchResultWithMenu : public SearchResult { public: - SearchResultWithMenu(const std::string& title, - const std::string& details) : menu_model_(NULL) { + SearchResultWithMenu(const std::string& title, const std::string& details) + : menu_model_(NULL), + menu_ready_(true) { set_title(ASCIIToUTF16(title)); set_details(ASCIIToUTF16(details)); menu_model_.AddItem(0, UTF8ToUTF16("Menu For: " + title)); } + void SetMenuReadyForTesting(bool ready) { + menu_ready_ = ready; + } + virtual ui::MenuModel* GetContextMenuModel() OVERRIDE { + if (!menu_ready_) + return NULL; + return &menu_model_; } private: ui::SimpleMenuModel menu_model_; + bool menu_ready_; DISALLOW_COPY_AND_ASSIGN(SearchResultWithMenu); }; @@ -87,6 +104,12 @@ class AppsSearchResultsControllerTest : public ui::CocoaTest { row:index]; } + void SetMenuReadyAt(size_t index, bool ready) { + SearchResultWithMenu* result = + static_cast<SearchResultWithMenu*>(ModelResultAt(index)); + result->SetMenuReadyForTesting(ready); + } + BOOL SimulateKeyAction(SEL c) { return [apps_search_results_controller_ handleCommandBySelector:c]; } @@ -260,10 +283,26 @@ TEST_F(AppsSearchResultsControllerTest, ContextMenus) { EXPECT_EQ(1, [menu numberOfItems]); EXPECT_NSEQ(@"Menu For: Result 0", [[menu itemAtIndex:0] title]); + // Test a context menu request while the item is still installing. + SetMenuReadyAt(1, false); + menu = [table_view menuForEvent:mouse_in_row_1]; + EXPECT_EQ(nil, menu); + + SetMenuReadyAt(1, true); menu = [table_view menuForEvent:mouse_in_row_1]; EXPECT_EQ(1, [menu numberOfItems]); EXPECT_NSEQ(@"Menu For: Result 1", [[menu itemAtIndex:0] title]); } +// Test that observing a search result item uninstall performs the search again. +TEST_F(AppsSearchResultsControllerTest, UninstallRedperformsSearch) { + base::MessageLoopForUI message_loop; + EXPECT_EQ(0, [delegate_ redoSearchCount]); + ModelResultAt(0)->NotifyItemUninstalled(); + message_loop.PostTask(FROM_HERE, base::MessageLoop::QuitClosure()); + message_loop.Run(); + EXPECT_EQ(1, [delegate_ redoSearchCount]); +} + } // namespace test } // namespace app_list diff --git a/chromium/ui/app_list/cocoa/apps_search_results_model_bridge.h b/chromium/ui/app_list/cocoa/apps_search_results_model_bridge.h index e1d70ac37ce..8939d260efb 100644 --- a/chromium/ui/app_list/cocoa/apps_search_results_model_bridge.h +++ b/chromium/ui/app_list/cocoa/apps_search_results_model_bridge.h @@ -7,11 +7,10 @@ #include "base/mac/scoped_nsobject.h" #include "base/memory/scoped_vector.h" -#include "ui/app_list/app_list_model.h" #include "ui/base/models/list_model_observer.h" @class NSMenu; -@class NSTableView; +@class AppsSearchResultsController; namespace app_list { @@ -19,8 +18,8 @@ namespace app_list { // and updating the NSTableView where they are displayed. class AppsSearchResultsModelBridge : public ui::ListModelObserver { public: - AppsSearchResultsModelBridge(AppListModel::SearchResults* results_model, - NSTableView* results_table_view); + explicit AppsSearchResultsModelBridge( + AppsSearchResultsController* results_controller); virtual ~AppsSearchResultsModelBridge(); // Returns the context menu for the item at |index| in the search results @@ -40,8 +39,7 @@ class AppsSearchResultsModelBridge : public ui::ListModelObserver { virtual void ListItemMoved(size_t index, size_t target_index) OVERRIDE; virtual void ListItemsChanged(size_t start, size_t count) OVERRIDE; - AppListModel::SearchResults* results_; // Weak. Owned by AppListModel. - base::scoped_nsobject<NSTableView> table_view_; + AppsSearchResultsController* parent_; // Weak. Owns us. ScopedVector<ItemObserver> item_observers_; DISALLOW_COPY_AND_ASSIGN(AppsSearchResultsModelBridge); diff --git a/chromium/ui/app_list/cocoa/apps_search_results_model_bridge.mm b/chromium/ui/app_list/cocoa/apps_search_results_model_bridge.mm index d56c5fd4296..69a3205ef06 100644 --- a/chromium/ui/app_list/cocoa/apps_search_results_model_bridge.mm +++ b/chromium/ui/app_list/cocoa/apps_search_results_model_bridge.mm @@ -7,6 +7,8 @@ #import <Cocoa/Cocoa.h> #include "base/strings/sys_string_conversions.h" +#include "ui/app_list/app_list_model.h" +#import "ui/app_list/cocoa/apps_search_results_controller.h" #include "ui/app_list/search_result.h" #include "ui/app_list/search_result_observer.h" #import "ui/base/cocoa/menu_controller.h" @@ -19,7 +21,7 @@ class AppsSearchResultsModelBridge::ItemObserver : public SearchResultObserver { : bridge_(bridge), row_in_view_(index) { // Cache the result, because the results array is updated before notifying // observers (which happens before deleting the SearchResult). - result_ = bridge_->results_->GetItemAt(index); + result_ = [bridge_->parent_ results]->GetItemAt(index); result_->AddObserver(this); } @@ -29,8 +31,12 @@ class AppsSearchResultsModelBridge::ItemObserver : public SearchResultObserver { NSMenu* GetContextMenu() { if (!context_menu_controller_) { + ui::MenuModel* menu_model = result_->GetContextMenuModel(); + if (!menu_model) + return nil; + context_menu_controller_.reset( - [[MenuController alloc] initWithModel:result_->GetContextMenuModel() + [[MenuController alloc] initWithModel:menu_model useWithPopUpButtonCell:NO]); } return [context_menu_controller_ menu]; @@ -44,7 +50,7 @@ class AppsSearchResultsModelBridge::ItemObserver : public SearchResultObserver { virtual void OnIsInstallingChanged() OVERRIDE {} virtual void OnPercentDownloadedChanged() OVERRIDE {} virtual void OnItemInstalled() OVERRIDE {} - virtual void OnItemUninstalled() OVERRIDE {} + virtual void OnItemUninstalled() OVERRIDE; private: AppsSearchResultsModelBridge* bridge_; // Weak. Owns us. @@ -55,17 +61,24 @@ class AppsSearchResultsModelBridge::ItemObserver : public SearchResultObserver { DISALLOW_COPY_AND_ASSIGN(ItemObserver); }; +void AppsSearchResultsModelBridge::ItemObserver::OnItemUninstalled() { + // Performing the search again will destroy |this|, so post a task. This also + // ensures that the AppSearchProvider has observed the uninstall before + // performing the search again, otherwise it will provide a NULL result. + [[bridge_->parent_ delegate] performSelector:@selector(redoSearch) + withObject:nil + afterDelay:0]; +} + AppsSearchResultsModelBridge::AppsSearchResultsModelBridge( - AppListModel::SearchResults* results_model, - NSTableView* results_table_view) - : results_(results_model), - table_view_([results_table_view retain]) { + AppsSearchResultsController* results_controller) + : parent_(results_controller) { UpdateItemObservers(); - results_->AddObserver(this); + [parent_ results]->AddObserver(this); } AppsSearchResultsModelBridge::~AppsSearchResultsModelBridge() { - results_->RemoveObserver(this); + [parent_ results]->RemoveObserver(this); } NSMenu* AppsSearchResultsModelBridge::MenuForItem(size_t index) { @@ -75,7 +88,7 @@ NSMenu* AppsSearchResultsModelBridge::MenuForItem(size_t index) { void AppsSearchResultsModelBridge::UpdateItemObservers() { DCHECK(item_observers_.empty()); - const size_t itemCount = results_->item_count(); + const size_t itemCount = [parent_ results]->item_count(); for (size_t i = 0 ; i < itemCount; ++i) item_observers_.push_back(new ItemObserver(this, i)); } @@ -85,27 +98,27 @@ void AppsSearchResultsModelBridge::ReloadDataForItems( NSIndexSet* column = [NSIndexSet indexSetWithIndex:0]; NSIndexSet* rows = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(start, count)]; - [table_view_ reloadDataForRowIndexes:rows - columnIndexes:column]; + [[parent_ tableView] reloadDataForRowIndexes:rows + columnIndexes:column]; } void AppsSearchResultsModelBridge::ListItemsAdded( size_t start, size_t count) { item_observers_.clear(); - if (start == static_cast<size_t>([table_view_ numberOfRows])) - [table_view_ noteNumberOfRowsChanged]; + if (start == static_cast<size_t>([[parent_ tableView] numberOfRows])) + [[parent_ tableView] noteNumberOfRowsChanged]; else - [table_view_ reloadData]; + [[parent_ tableView] reloadData]; UpdateItemObservers(); } void AppsSearchResultsModelBridge::ListItemsRemoved( size_t start, size_t count) { item_observers_.clear(); - if (start == results_->item_count()) - [table_view_ noteNumberOfRowsChanged]; + if (start == [parent_ results]->item_count()) + [[parent_ tableView] noteNumberOfRowsChanged]; else - [table_view_ reloadData]; + [[parent_ tableView] reloadData]; UpdateItemObservers(); } diff --git a/chromium/ui/app_list/cocoa/current_user_menu_item_view.h b/chromium/ui/app_list/cocoa/current_user_menu_item_view.h deleted file mode 100644 index 84c240a4bec..00000000000 --- a/chromium/ui/app_list/cocoa/current_user_menu_item_view.h +++ /dev/null @@ -1,24 +0,0 @@ -// 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. - -#ifndef UI_APP_LIST_COCOA_CURRENT_USER_MENU_ITEM_VIEW_H_ -#define UI_APP_LIST_COCOA_CURRENT_USER_MENU_ITEM_VIEW_H_ - -#import <Cocoa/Cocoa.h> - -#include "ui/app_list/app_list_export.h" - -namespace app_list { -class AppListViewDelegate; -} - -// The custom in-menu view representing the currently signed-in user. -APP_LIST_EXPORT -@interface CurrentUserMenuItemView : NSView - -- (id)initWithDelegate:(app_list::AppListViewDelegate*)delegate; - -@end - -#endif // UI_APP_LIST_COCOA_CURRENT_USER_MENU_ITEM_VIEW_H_ diff --git a/chromium/ui/app_list/cocoa/current_user_menu_item_view.mm b/chromium/ui/app_list/cocoa/current_user_menu_item_view.mm deleted file mode 100644 index 6aac34c6a99..00000000000 --- a/chromium/ui/app_list/cocoa/current_user_menu_item_view.mm +++ /dev/null @@ -1,85 +0,0 @@ -// 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. - -#import "ui/app_list/cocoa/current_user_menu_item_view.h" - -#include "base/logging.h" -#include "base/mac/scoped_nsobject.h" -#include "base/strings/sys_string_conversions.h" -#include "grit/ui_resources.h" -#include "ui/app_list/app_list_view_delegate.h" -#include "ui/base/resource/resource_bundle.h" - -namespace { - -// Padding on the left of the indicator icon. -const CGFloat kMenuLeftMargin = 3; - -} - -@interface CurrentUserMenuItemView () - -// Adds a text label in the custom view in the menu showing the current user. -- (NSTextField*)addLabelWithFrame:(NSPoint)origin - labelText:(const string16&)labelText; - -@end - -@implementation CurrentUserMenuItemView - -- (id)initWithDelegate:(app_list::AppListViewDelegate*)delegate { - DCHECK(delegate); - if ((self = [super initWithFrame:NSZeroRect])) { - NSImage* userImage = ui::ResourceBundle::GetSharedInstance(). - GetNativeImageNamed(IDR_APP_LIST_USER_INDICATOR).AsNSImage(); - NSRect imageRect = NSMakeRect(kMenuLeftMargin, 0, 0, 0); - imageRect.size = [userImage size]; - base::scoped_nsobject<NSImageView> userImageView( - [[NSImageView alloc] initWithFrame:imageRect]); - [userImageView setImage:userImage]; - [self addSubview:userImageView]; - - NSPoint labelOrigin = NSMakePoint(NSMaxX(imageRect), 0); - NSTextField* userField = - [self addLabelWithFrame:labelOrigin - labelText:delegate->GetCurrentUserName()]; - - labelOrigin.y = NSMaxY([userField frame]); - NSTextField* emailField = - [self addLabelWithFrame:labelOrigin - labelText:delegate->GetCurrentUserEmail()]; - [emailField setTextColor:[NSColor disabledControlTextColor]]; - - // Size the container view to fit the longest label. - NSRect labelFrame = [emailField frame]; - if (NSWidth([userField frame]) > NSWidth(labelFrame)) - labelFrame.size.width = NSWidth([userField frame]); - [self setFrameSize:NSMakeSize( - NSMaxX(labelFrame) + NSMaxX(imageRect), - NSMaxY(labelFrame))]; - } - return self; -} - -- (NSTextField*)addLabelWithFrame:(NSPoint)origin - labelText:(const string16&)labelText { - NSRect labelFrame = NSZeroRect; - labelFrame.origin = origin; - base::scoped_nsobject<NSTextField> label( - [[NSTextField alloc] initWithFrame:labelFrame]); - [label setStringValue:base::SysUTF16ToNSString(labelText)]; - [label setEditable:NO]; - [label setBordered:NO]; - [label setDrawsBackground:NO]; - [label setFont:[NSFont menuFontOfSize:0]]; - [label sizeToFit]; - [self addSubview:label]; - return label.autorelease(); -} - -- (BOOL)isFlipped { - return YES; -} - -@end diff --git a/chromium/ui/app_list/pagination_model.cc b/chromium/ui/app_list/pagination_model.cc index 2bf69020ab8..5e8d655a375 100644 --- a/chromium/ui/app_list/pagination_model.cc +++ b/chromium/ui/app_list/pagination_model.cc @@ -7,7 +7,7 @@ #include <algorithm> #include "ui/app_list/pagination_model_observer.h" -#include "ui/base/animation/slide_animation.h" +#include "ui/gfx/animation/slide_animation.h" namespace app_list { @@ -32,7 +32,7 @@ void PaginationModel::SetTotalPages(int total_pages) { if (selected_page_ < 0) SelectPage(0, false /* animate */); if (selected_page_ >= total_pages_) - SelectPage(total_pages_ - 1, false /* animate */); + SelectPage(std::max(total_pages_ - 1, 0), false /* animate */); FOR_EACH_OBSERVER(PaginationModelObserver, observers_, TotalPagesChanged()); } @@ -82,7 +82,7 @@ void PaginationModel::SelectPage(int page, bool animate) { } } } else { - DCHECK(page >= 0 && page < total_pages_); + DCHECK(total_pages_ == 0 || (page >= 0 && page < total_pages_)); if (page == selected_page_) return; @@ -221,8 +221,8 @@ void PaginationModel::StartTransitionAnimation(const Transition& transition) { NotifyTransitionStarted(); SetTransition(transition); - transition_animation_.reset(new ui::SlideAnimation(this)); - transition_animation_->SetTweenType(ui::Tween::LINEAR); + transition_animation_.reset(new gfx::SlideAnimation(this)); + transition_animation_->SetTweenType(gfx::Tween::LINEAR); transition_animation_->Reset(transition_.progress); const int duration = is_valid_page(transition_.target_page) ? @@ -240,12 +240,12 @@ void PaginationModel::ResetTransitionAnimation() { pending_selected_page_ = -1; } -void PaginationModel::AnimationProgressed(const ui::Animation* animation) { +void PaginationModel::AnimationProgressed(const gfx::Animation* animation) { transition_.progress = transition_animation_->GetCurrentValue(); NotifyTransitionChanged(); } -void PaginationModel::AnimationEnded(const ui::Animation* animation) { +void PaginationModel::AnimationEnded(const gfx::Animation* animation) { // Save |pending_selected_page_| because SelectPage resets it. int next_target = pending_selected_page_; diff --git a/chromium/ui/app_list/pagination_model.h b/chromium/ui/app_list/pagination_model.h index 00ddd96e818..0546adc4bf8 100644 --- a/chromium/ui/app_list/pagination_model.h +++ b/chromium/ui/app_list/pagination_model.h @@ -11,9 +11,9 @@ #include "base/observer_list.h" #include "base/time/time.h" #include "ui/app_list/app_list_export.h" -#include "ui/base/animation/animation_delegate.h" +#include "ui/gfx/animation/animation_delegate.h" -namespace ui { +namespace gfx { class SlideAnimation; } @@ -24,7 +24,7 @@ class PaginationModelObserver; // A simple pagination model that consists of two numbers: the total pages and // the currently selected page. The model is a single selection model that at // the most one page can become selected at any time. -class APP_LIST_EXPORT PaginationModel : public ui::AnimationDelegate { +class APP_LIST_EXPORT PaginationModel : public gfx::AnimationDelegate { public: // Holds info for transition animation and touch scroll. struct Transition { @@ -113,9 +113,9 @@ class APP_LIST_EXPORT PaginationModel : public ui::AnimationDelegate { void StartTransitionAnimation(const Transition& transition); void ResetTransitionAnimation(); - // ui::AnimationDelegate overrides: - virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; - virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE; + // gfx::AnimationDelegate overrides: + virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; + virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE; int total_pages_; int selected_page_; @@ -127,7 +127,7 @@ class APP_LIST_EXPORT PaginationModel : public ui::AnimationDelegate { // last target page is remembered here. int pending_selected_page_; - scoped_ptr<ui::SlideAnimation> transition_animation_; + scoped_ptr<gfx::SlideAnimation> transition_animation_; int transition_duration_ms_; // Transition duration in millisecond. int overscroll_transition_duration_ms_; diff --git a/chromium/ui/app_list/search_result.h b/chromium/ui/app_list/search_result.h index 5baa50f5579..e8e265fa70b 100644 --- a/chromium/ui/app_list/search_result.h +++ b/chromium/ui/app_list/search_result.h @@ -12,8 +12,8 @@ #include "base/strings/string16.h" #include "ui/app_list/app_list_export.h" #include "ui/base/models/list_model.h" -#include "ui/base/range/range.h" #include "ui/gfx/image/image_skia.h" +#include "ui/gfx/range/range.h" namespace ui { class MenuModel; @@ -45,7 +45,7 @@ class APP_LIST_EXPORT SearchResult { } int styles; - ui::Range range; + gfx::Range range; }; typedef std::vector<Tag> Tags; @@ -106,7 +106,8 @@ class APP_LIST_EXPORT SearchResult { void AddObserver(SearchResultObserver* observer); void RemoveObserver(SearchResultObserver* observer); - // Returns the context menu model for this item. + // Returns the context menu model for this item, or NULL if there is currently + // no menu for the item (e.g. during install). // Note the returned menu model is owned by this item. virtual ui::MenuModel* GetContextMenuModel(); diff --git a/chromium/ui/app_list/signin_delegate.cc b/chromium/ui/app_list/signin_delegate.cc index 51eb8305019..b0dd7e67590 100644 --- a/chromium/ui/app_list/signin_delegate.cc +++ b/chromium/ui/app_list/signin_delegate.cc @@ -3,7 +3,6 @@ // found in the LICENSE file. #include "ui/app_list/signin_delegate.h" -#include "ui/app_list/signin_delegate_observer.h" namespace app_list { @@ -11,17 +10,4 @@ SigninDelegate::SigninDelegate() {} SigninDelegate::~SigninDelegate() {} -void SigninDelegate::AddObserver(SigninDelegateObserver* observer) { - observers_.AddObserver(observer); -} - -void SigninDelegate::RemoveObserver(SigninDelegateObserver* observer) { - observers_.RemoveObserver(observer); -} - -void SigninDelegate::NotifySigninSuccess() { - FOR_EACH_OBSERVER(app_list::SigninDelegateObserver, observers_, - OnSigninSuccess()); -} - } // namespace app_list diff --git a/chromium/ui/app_list/signin_delegate.h b/chromium/ui/app_list/signin_delegate.h index eda67f410e8..54f59179de9 100644 --- a/chromium/ui/app_list/signin_delegate.h +++ b/chromium/ui/app_list/signin_delegate.h @@ -6,14 +6,11 @@ #define UI_APP_LIST_SIGNIN_DELEGATE_H_ #include "base/basictypes.h" -#include "base/observer_list.h" #include "base/strings/string16.h" #include "ui/app_list/app_list_export.h" namespace app_list { -class SigninDelegateObserver; - class APP_LIST_EXPORT SigninDelegate { public: SigninDelegate(); @@ -30,15 +27,7 @@ class APP_LIST_EXPORT SigninDelegate { virtual base::string16 GetLearnMoreLinkText() = 0; virtual base::string16 GetSettingsLinkText() = 0; - void AddObserver(SigninDelegateObserver* observer); - void RemoveObserver(SigninDelegateObserver* observer); - - protected: - void NotifySigninSuccess(); - private: - ObserverList<SigninDelegateObserver, true> observers_; - DISALLOW_COPY_AND_ASSIGN(SigninDelegate); }; diff --git a/chromium/ui/app_list/signin_delegate_observer.h b/chromium/ui/app_list/signin_delegate_observer.h deleted file mode 100644 index 47c499260ef..00000000000 --- a/chromium/ui/app_list/signin_delegate_observer.h +++ /dev/null @@ -1,24 +0,0 @@ -// 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. - -#ifndef UI_APP_LIST_SIGNIN_DELEGATE_OBSERVER_H_ -#define UI_APP_LIST_SIGNIN_DELEGATE_OBSERVER_H_ - -#include "ui/app_list/app_list_export.h" - -namespace app_list { - -// Abstract interface to allow handling app list signin success. -class APP_LIST_EXPORT SigninDelegateObserver { - public: - // Called by the SigninDelegate when signin has successfully completed. - virtual void OnSigninSuccess() = 0; - - protected: - virtual ~SigninDelegateObserver() {} -}; - -} // namespace app_list - -#endif // UI_APP_LIST_SIGNIN_DELEGATE_OBSERVER_H_ diff --git a/chromium/ui/app_list/views/app_list_item_view.cc b/chromium/ui/app_list/views/app_list_item_view.cc index 1b9aaf701d1..2717f51a825 100644 --- a/chromium/ui/app_list/views/app_list_item_view.cc +++ b/chromium/ui/app_list/views/app_list_item_view.cc @@ -13,11 +13,11 @@ #include "ui/app_list/views/cached_label.h" #include "ui/app_list/views/progress_bar_view.h" #include "ui/base/accessibility/accessible_view_state.h" -#include "ui/base/animation/throb_animation.h" #include "ui/base/dragdrop/drag_utils.h" #include "ui/base/resource/resource_bundle.h" #include "ui/compositor/layer.h" #include "ui/compositor/scoped_layer_animation_settings.h" +#include "ui/gfx/animation/throb_animation.h" #include "ui/gfx/canvas.h" #include "ui/gfx/font.h" #include "ui/gfx/image/image_skia_operations.h" @@ -130,6 +130,11 @@ void AppListItemView::UpdateIcon() { icon_->SetImage(resized); } +void AppListItemView::UpdateTooltip() { + title_->SetTooltipText(model_->title() == model_->full_name() ? + string16() : UTF8ToUTF16(model_->full_name())); +} + void AppListItemView::SetUIState(UIState state) { if (ui_state_ == state) return; @@ -193,6 +198,7 @@ void AppListItemView::ItemIconChanged() { void AppListItemView::ItemTitleChanged() { title_->SetText(UTF8ToUTF16(model_->title())); title_->Invalidate(); + UpdateTooltip(); Layout(); } diff --git a/chromium/ui/app_list/views/app_list_item_view.h b/chromium/ui/app_list/views/app_list_item_view.h index 0738d83c7e7..311d7219456 100644 --- a/chromium/ui/app_list/views/app_list_item_view.h +++ b/chromium/ui/app_list/views/app_list_item_view.h @@ -62,6 +62,9 @@ class APP_LIST_EXPORT AppListItemView : public views::CustomButton, // Get icon from model and schedule background processing. void UpdateIcon(); + // Update the tooltip text from the model. + void UpdateTooltip(); + void SetUIState(UIState state); // Sets |touch_dragging_| flag and updates UI. diff --git a/chromium/ui/app_list/views/app_list_main_view.cc b/chromium/ui/app_list/views/app_list_main_view.cc index fa0de27ce0e..f08fef82d9b 100644 --- a/chromium/ui/app_list/views/app_list_main_view.cc +++ b/chromium/ui/app_list/views/app_list_main_view.cc @@ -6,8 +6,10 @@ #include <algorithm> +#include "base/bind.h" #include "base/callback.h" #include "base/files/file_path.h" +#include "base/message_loop/message_loop.h" #include "base/strings/string_util.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_item_model.h" @@ -77,13 +79,14 @@ class AppListMainView::IconLoader : public AppListItemModelObserver { AppListMainView::AppListMainView(AppListViewDelegate* delegate, AppListModel* model, PaginationModel* pagination_model, - views::View* anchor) + gfx::NativeView parent) : delegate_(delegate), model_(model), search_box_view_(NULL), - contents_view_(NULL) { + contents_view_(NULL), + weak_ptr_factory_(this) { // Starts icon loading early. - PreloadIcons(pagination_model, anchor); + PreloadIcons(pagination_model, parent); SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, kInnerPadding, @@ -127,6 +130,7 @@ void AppListMainView::ShowAppListWhenReady() { void AppListMainView::Close() { icon_loading_wait_timer_.Stop(); + contents_view_->CancelDrag(); } void AppListMainView::Prerender() { @@ -134,17 +138,15 @@ void AppListMainView::Prerender() { } void AppListMainView::SetDragAndDropHostOfCurrentAppList( - app_list::ApplicationDragAndDropHost* drag_and_drop_host) { + ApplicationDragAndDropHost* drag_and_drop_host) { contents_view_->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host); } void AppListMainView::PreloadIcons(PaginationModel* pagination_model, - views::View* anchor) { + gfx::NativeView parent) { ui::ScaleFactor scale_factor = ui::SCALE_FACTOR_100P; - if (anchor && anchor->GetWidget()) { - scale_factor = ui::GetScaleFactorForNativeView( - anchor->GetWidget()->GetNativeView()); - } + if (parent) + scale_factor = ui::GetScaleFactorForNativeView(parent); // |pagination_model| could have -1 as the initial selected page and // assumes first page (i.e. index 0) will be used in this case. @@ -230,7 +232,13 @@ void AppListMainView::OnResultInstalled(SearchResult* result) { } void AppListMainView::OnResultUninstalled(SearchResult* result) { - QueryChanged(search_box_view_); + // Resubmit the query via a posted task so that all observers for the + // uninstall notification are notified. + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&AppListMainView::QueryChanged, + weak_ptr_factory_.GetWeakPtr(), + search_box_view_)); } } // namespace app_list diff --git a/chromium/ui/app_list/views/app_list_main_view.h b/chromium/ui/app_list/views/app_list_main_view.h index 1909d97c1da..0c9a7383e12 100644 --- a/chromium/ui/app_list/views/app_list_main_view.h +++ b/chromium/ui/app_list/views/app_list_main_view.h @@ -8,10 +8,11 @@ #include <string> #include "base/memory/scoped_vector.h" +#include "base/memory/weak_ptr.h" #include "base/timer/timer.h" -#include "ui/app_list/apps_grid_view_delegate.h" -#include "ui/app_list/search_box_view_delegate.h" -#include "ui/app_list/search_result_list_view_delegate.h" +#include "ui/app_list/views/apps_grid_view_delegate.h" +#include "ui/app_list/views/search_box_view_delegate.h" +#include "ui/app_list/views/search_result_list_view_delegate.h" #include "ui/views/view.h" namespace views { @@ -39,7 +40,7 @@ class AppListMainView : public views::View, explicit AppListMainView(AppListViewDelegate* delegate, AppListModel* model, PaginationModel* pagination_model, - views::View* anchor); + gfx::NativeView parent); virtual ~AppListMainView(); void ShowAppListWhenReady(); @@ -59,9 +60,9 @@ class AppListMainView : public views::View, class IconLoader; // Loads icon image for the apps in the selected page of |pagination_model|. - // |anchor| is used to determine the image scale factor to use. + // |parent| is used to determine the image scale factor to use. void PreloadIcons(PaginationModel* pagination_model, - views::View* anchor); + gfx::NativeView parent); // Invoked when |icon_loading_wait_timer_| fires. void OnIconLoadingWaitTimer(); @@ -99,6 +100,8 @@ class AppListMainView : public views::View, ScopedVector<IconLoader> pending_icon_loaders_; + base::WeakPtrFactory<AppListMainView> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(AppListMainView); }; diff --git a/chromium/ui/app_list/views/app_list_menu_views.cc b/chromium/ui/app_list/views/app_list_menu_views.cc index 0eb853607f0..04c1f2155b4 100644 --- a/chromium/ui/app_list/views/app_list_menu_views.cc +++ b/chromium/ui/app_list/views/app_list_menu_views.cc @@ -5,6 +5,7 @@ #include "ui/app_list/views/app_list_menu_views.h" #include "grit/ui_resources.h" +#include "ui/app_list/app_list_model.h" #include "ui/app_list/app_list_view_delegate.h" #include "ui/base/resource/resource_bundle.h" #include "ui/views/controls/button/menu_button.h" @@ -19,114 +20,10 @@ using views::MenuItemView; namespace app_list { -namespace { - -class CurrentUserView : public views::View { - public: - CurrentUserView(const base::string16& user_name, - const base::string16& user_email, - const gfx::ImageSkia& icon) { - const views::MenuConfig& menu_config = views::MenuConfig::instance(NULL); - views::GridLayout* layout = new views::GridLayout(this); - int item_right_padding = menu_config.label_to_arrow_padding + - menu_config.arrow_width + - menu_config.arrow_to_edge_padding; - - layout->SetInsets(0, 0, 0, item_right_padding); - SetLayoutManager(layout); - - views::ColumnSet* columns = layout->AddColumnSet(0); - columns->AddColumn(views::GridLayout::FILL, - views::GridLayout::FILL, - 0, - views::GridLayout::USE_PREF, - 0, - menu_config.check_width + menu_config.item_left_margin); - columns->AddColumn(views::GridLayout::FILL, - views::GridLayout::FILL, - 1, - views::GridLayout::USE_PREF, - 0, - 0); - - layout->StartRow(0, 0); - views::ImageView* image_view = new views::ImageView(); - image_view->SetImage(icon); - layout->AddView(image_view); - - views::Label* user_name_view = new views::Label(user_name); - user_name_view->SetHorizontalAlignment(gfx::ALIGN_LEFT); - layout->AddView(user_name_view); - - layout->StartRow(0, 0); - views::Label* user_email_view = new views::Label(user_email); - user_email_view->SetHorizontalAlignment(gfx::ALIGN_LEFT); - user_email_view->SetEnabled(false); - layout->SkipColumns(1); - layout->AddView(user_email_view); - } - - private: - DISALLOW_COPY_AND_ASSIGN(CurrentUserView); -}; - -class CurrentUserMenuItem : public MenuItemView { - public: - CurrentUserMenuItem(MenuItemView* parent, - int id, - const base::string16& user_name, - const base::string16& user_email, - const gfx::ImageSkia& icon) - : MenuItemView(parent, id, MenuItemView::NORMAL) { - AddChildView(new CurrentUserView(user_name, user_email, icon)); - } - - private: - DISALLOW_COPY_AND_ASSIGN(CurrentUserMenuItem); -}; - -class AppListMenuModelAdapter : public views::MenuModelAdapter { - public: - AppListMenuModelAdapter(ui::MenuModel* menu_model, - AppListViewDelegate* delegate) - : views::MenuModelAdapter(menu_model), - delegate_(delegate) {} - virtual ~AppListMenuModelAdapter() {} - - // Overridden from views::MenuModelAdapter: - virtual MenuItemView* AppendMenuItem(MenuItemView* menu, - ui::MenuModel* model, - int index) OVERRIDE { - if (!delegate_) - return NULL; - - int id = model->GetCommandIdAt(index); - if (id != AppListMenu::CURRENT_USER) - return MenuModelAdapter::AppendMenuItem(menu, model, index); - - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - MenuItemView* item = new CurrentUserMenuItem( - menu, - id, - delegate_->GetCurrentUserName(), - delegate_->GetCurrentUserEmail(), - *rb.GetImageSkiaNamed(IDR_APP_LIST_USER_INDICATOR)); - menu->CreateSubmenu(); - menu->GetSubmenu()->AddChildViewAt(item, index); - return item; - } - - private: - AppListViewDelegate* delegate_; - - DISALLOW_COPY_AND_ASSIGN(AppListMenuModelAdapter); -}; - -} // namespace - -AppListMenuViews::AppListMenuViews(AppListViewDelegate* delegate) - : AppListMenu(delegate) { - menu_delegate_.reset(new AppListMenuModelAdapter(menu_model(), delegate)); +AppListMenuViews::AppListMenuViews(AppListViewDelegate* delegate, + AppListModel* app_list_model) + : AppListMenu(delegate, app_list_model->users()) { + menu_delegate_.reset(new views::MenuModelAdapter(menu_model())); menu_ = new MenuItemView(menu_delegate_.get()); menu_runner_.reset(new views::MenuRunner(menu_)); menu_delegate_->BuildMenu(menu_); diff --git a/chromium/ui/app_list/views/app_list_menu_views.h b/chromium/ui/app_list/views/app_list_menu_views.h index 15f3dbb1f85..2dc3d01f046 100644 --- a/chromium/ui/app_list/views/app_list_menu_views.h +++ b/chromium/ui/app_list/views/app_list_menu_views.h @@ -20,11 +20,14 @@ class MenuButton; namespace app_list { +class AppListModel; + // Views implementation of the app list menu. // TODO(benwells): We should consider moving this into Chrome. -class AppListMenuViews : public app_list::AppListMenu { +class AppListMenuViews : public AppListMenu { public: - explicit AppListMenuViews(AppListViewDelegate* delegate); + AppListMenuViews(AppListViewDelegate* delegate, + AppListModel* model); virtual ~AppListMenuViews(); void RunMenuAt(views::MenuButton* button, const gfx::Point& point); diff --git a/chromium/ui/app_list/views/app_list_view.cc b/chromium/ui/app_list/views/app_list_view.cc index 118ab2b3409..ae4647ff2c3 100644 --- a/chromium/ui/app_list/views/app_list_view.cc +++ b/chromium/ui/app_list/views/app_list_view.cc @@ -4,6 +4,7 @@ #include "ui/app_list/views/app_list_view.h" +#include "base/callback.h" #include "base/command_line.h" #include "base/strings/string_util.h" #include "ui/app_list/app_list_constants.h" @@ -37,6 +38,8 @@ namespace app_list { namespace { +base::Closure g_next_paint_callback; + // The distance between the arrow tip and edge of the anchor view. const int kArrowOffset = 10; @@ -51,83 +54,38 @@ AppListView::AppListView(AppListViewDelegate* delegate) app_list_main_view_(NULL), signin_view_(NULL) { if (delegate_) - delegate_->SetModel(model_.get()); - if (GetSigninDelegate()) - GetSigninDelegate()->AddObserver(this); + delegate_->InitModel(model_.get()); + model_->AddObserver(this); } AppListView::~AppListView() { - if (GetSigninDelegate()) - GetSigninDelegate()->RemoveObserver(this); - + model_->RemoveObserver(this); // Models are going away, ensure their references are cleared. RemoveAllChildViews(true); } -void AppListView::InitAsBubble(gfx::NativeView parent, - PaginationModel* pagination_model, - views::View* anchor, - const gfx::Point& anchor_point, - views::BubbleBorder::Arrow arrow, - bool border_accepts_events) { - app_list_main_view_ = new AppListMainView(delegate_.get(), - model_.get(), - pagination_model, - anchor); - AddChildView(app_list_main_view_); -#if defined(USE_AURA) - app_list_main_view_->SetPaintToLayer(true); - app_list_main_view_->SetFillsBoundsOpaquely(false); - app_list_main_view_->layer()->SetMasksToBounds(true); -#endif - - signin_view_ = new SigninView( - GetSigninDelegate(), - app_list_main_view_->GetPreferredSize().width()); - AddChildView(signin_view_); - - OnSigninStatusChanged(); - +void AppListView::InitAsBubbleAttachedToAnchor( + gfx::NativeView parent, + PaginationModel* pagination_model, + views::View* anchor, + const gfx::Vector2d& anchor_offset, + views::BubbleBorder::Arrow arrow, + bool border_accepts_events) { set_anchor_view(anchor); - set_anchor_rect(gfx::Rect(anchor_point, gfx::Size())); - set_color(kContentsBackgroundColor); - set_margins(gfx::Insets()); - set_move_with_anchor(true); - set_parent_window(parent); - set_close_on_deactivate(false); - set_close_on_esc(false); - set_anchor_view_insets(gfx::Insets(kArrowOffset, kArrowOffset, - kArrowOffset, kArrowOffset)); - set_border_accepts_events(border_accepts_events); - set_shadow(views::BubbleBorder::BIG_SHADOW); -#if defined(USE_AURA) && defined(OS_WIN) - if (!ui::win::IsAeroGlassEnabled() || - CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableDwmComposition)) { - set_shadow(views::BubbleBorder::NO_SHADOW_OPAQUE_BORDER); - } -#endif - views::BubbleDelegateView::CreateBubble(this); - SetBubbleArrow(arrow); - -#if defined(USE_AURA) - GetWidget()->GetNativeWindow()->layer()->SetMasksToBounds(true); - GetBubbleFrameView()->set_background(new AppListBackground( - GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius(), - app_list_main_view_)); - set_background(NULL); -#else - set_background(new AppListBackground( - GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius(), - app_list_main_view_)); + InitAsBubbleInternal( + parent, pagination_model, arrow, border_accepts_events, anchor_offset); +} - // On non-aura the bubble has two widgets, and it's possible for the border - // to be shown independently in odd situations. Explicitly hide the bubble - // widget to ensure that any WM_WINDOWPOSCHANGED messages triggered by the - // window manager do not have the SWP_SHOWWINDOW flag set which would cause - // the border to be shown. See http://crbug.com/231687 . - GetWidget()->Hide(); -#endif +void AppListView::InitAsBubbleAtFixedLocation( + gfx::NativeView parent, + PaginationModel* pagination_model, + const gfx::Point& anchor_point_in_screen, + views::BubbleBorder::Arrow arrow, + bool border_accepts_events) { + set_anchor_view(NULL); + set_anchor_rect(gfx::Rect(anchor_point_in_screen, gfx::Size())); + InitAsBubbleInternal( + parent, pagination_model, arrow, border_accepts_events, gfx::Vector2d()); } void AppListView::SetBubbleArrow(views::BubbleBorder::Arrow arrow) { @@ -142,7 +100,7 @@ void AppListView::SetAnchorPoint(const gfx::Point& anchor_point) { } void AppListView::SetDragAndDropHostOfCurrentAppList( - app_list::ApplicationDragAndDropHost* drag_and_drop_host) { + ApplicationDragAndDropHost* drag_and_drop_host) { app_list_main_view_->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host); } @@ -166,6 +124,14 @@ gfx::Size AppListView::GetPreferredSize() { return app_list_main_view_->GetPreferredSize(); } +void AppListView::Paint(gfx::Canvas* canvas) { + views::BubbleDelegateView::Paint(canvas); + if (!g_next_paint_callback.is_null()) { + g_next_paint_callback.Run(); + g_next_paint_callback.Reset(); + } +} + bool AppListView::ShouldHandleSystemCommands() const { return true; } @@ -175,14 +141,28 @@ void AppListView::Prerender() { } void AppListView::OnSigninStatusChanged() { - const bool needs_signin = - GetSigninDelegate() && GetSigninDelegate()->NeedSignin(); - - signin_view_->SetVisible(needs_signin); - app_list_main_view_->SetVisible(!needs_signin); + signin_view_->SetVisible(!model_->signed_in()); + app_list_main_view_->SetVisible(model_->signed_in()); app_list_main_view_->search_box_view()->InvalidateMenu(); } +void AppListView::SetProfileByPath(const base::FilePath& profile_path) { + delegate_->SetProfileByPath(profile_path); +} + +void AppListView::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void AppListView::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +// static +void AppListView::SetNextPaintCallback(const base::Closure& callback) { + g_next_paint_callback = callback; +} + #if defined(OS_WIN) HWND AppListView::GetHWND() const { #if defined(USE_AURA) @@ -195,6 +175,71 @@ HWND AppListView::GetHWND() const { } #endif +void AppListView::InitAsBubbleInternal(gfx::NativeView parent, + PaginationModel* pagination_model, + views::BubbleBorder::Arrow arrow, + bool border_accepts_events, + const gfx::Vector2d& anchor_offset) { + app_list_main_view_ = new AppListMainView(delegate_.get(), + model_.get(), + pagination_model, + parent); + AddChildView(app_list_main_view_); +#if defined(USE_AURA) + app_list_main_view_->SetPaintToLayer(true); + app_list_main_view_->SetFillsBoundsOpaquely(false); + app_list_main_view_->layer()->SetMasksToBounds(true); +#endif + + signin_view_ = new SigninView( + delegate_ ? delegate_->GetSigninDelegate() + : NULL, + app_list_main_view_->GetPreferredSize().width()); + AddChildView(signin_view_); + + OnSigninStatusChanged(); + set_color(kContentsBackgroundColor); + set_margins(gfx::Insets()); + set_move_with_anchor(true); + set_parent_window(parent); + set_close_on_deactivate(false); + set_close_on_esc(false); + set_anchor_view_insets(gfx::Insets(kArrowOffset + anchor_offset.y(), + kArrowOffset + anchor_offset.x(), + kArrowOffset - anchor_offset.y(), + kArrowOffset - anchor_offset.x())); + set_border_accepts_events(border_accepts_events); + set_shadow(views::BubbleBorder::BIG_SHADOW); +#if defined(USE_AURA) && defined(OS_WIN) + if (!ui::win::IsAeroGlassEnabled() || + CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableDwmComposition)) { + set_shadow(views::BubbleBorder::NO_SHADOW_OPAQUE_BORDER); + } +#endif + views::BubbleDelegateView::CreateBubble(this); + SetBubbleArrow(arrow); + +#if defined(USE_AURA) + GetWidget()->GetNativeWindow()->layer()->SetMasksToBounds(true); + GetBubbleFrameView()->set_background(new AppListBackground( + GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius(), + app_list_main_view_)); + set_background(NULL); +#else + set_background(new AppListBackground( + GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius(), + app_list_main_view_)); + + // On non-aura the bubble has two widgets, and it's possible for the border + // to be shown independently in odd situations. Explicitly hide the bubble + // widget to ensure that any WM_WINDOWPOSCHANGED messages triggered by the + // window manager do not have the SWP_SHOWWINDOW flag set which would cause + // the border to be shown. See http://crbug.com/231687 . + GetWidget()->Hide(); +#endif +} + views::View* AppListView::GetInitiallyFocusedView() { return app_list_main_view_->search_box_view()->search_box(); } @@ -247,8 +292,9 @@ void AppListView::OnWidgetActivationChanged(views::Widget* widget, bool active) { // Do not called inherited function as the bubble delegate auto close // functionality is not used. - if (delegate_ && widget == GetWidget()) - delegate_->ViewActivationChanged(active); + if (widget == GetWidget()) + FOR_EACH_OBSERVER(Observer, observers_, + OnActivationChanged(widget, active)); } void AppListView::OnWidgetVisibilityChanged(views::Widget* widget, @@ -268,12 +314,12 @@ void AppListView::OnWidgetVisibilityChanged(views::Widget* widget, Layout(); } -void AppListView::OnSigninSuccess() { +void AppListView::OnAppListModelSigninStatusChanged() { OnSigninStatusChanged(); } -SigninDelegate* AppListView::GetSigninDelegate() { - return delegate_ ? delegate_->GetSigninDelegate() : NULL; +void AppListView::OnAppListModelUsersChanged() { + OnSigninStatusChanged(); } } // namespace app_list diff --git a/chromium/ui/app_list/views/app_list_view.h b/chromium/ui/app_list/views/app_list_view.h index fff4815ba1b..38564949307 100644 --- a/chromium/ui/app_list/views/app_list_view.h +++ b/chromium/ui/app_list/views/app_list_view.h @@ -5,11 +5,17 @@ #ifndef UI_APP_LIST_VIEWS_APP_LIST_VIEW_H_ #define UI_APP_LIST_VIEWS_APP_LIST_VIEW_H_ +#include "base/callback_forward.h" #include "base/memory/scoped_ptr.h" +#include "base/observer_list.h" #include "ui/app_list/app_list_export.h" -#include "ui/app_list/signin_delegate_observer.h" +#include "ui/app_list/app_list_model_observer.h" #include "ui/views/bubble/bubble_delegate.h" +namespace base { +class FilePath; +} + namespace views { class Widget; } @@ -26,19 +32,33 @@ class SigninView; // AppListView is the top-level view and controller of app list UI. It creates // and hosts a AppsGridView and passes AppListModel to it for display. class APP_LIST_EXPORT AppListView : public views::BubbleDelegateView, - public SigninDelegateObserver { + public AppListModelObserver { public: + class Observer { + public: + virtual void OnActivationChanged(views::Widget* widget, bool active) = 0; + }; + // Takes ownership of |delegate|. explicit AppListView(AppListViewDelegate* delegate); virtual ~AppListView(); - // Initializes the widget. - void InitAsBubble(gfx::NativeView parent, - PaginationModel* pagination_model, - views::View* anchor, - const gfx::Point& anchor_point, - views::BubbleBorder::Arrow arrow, - bool border_accepts_events); + // Initializes the widget and use a given |anchor| plus an |anchor_offset| for + // positioning. + void InitAsBubbleAttachedToAnchor(gfx::NativeView parent, + PaginationModel* pagination_model, + views::View* anchor, + const gfx::Vector2d& anchor_offset, + views::BubbleBorder::Arrow arrow, + bool border_accepts_events); + + // Initializes the widget and use a fixed |anchor_point_in_screen| for + // positioning. + void InitAsBubbleAtFixedLocation(gfx::NativeView parent, + PaginationModel* pagination_model, + const gfx::Point& anchor_point_in_screen, + views::BubbleBorder::Arrow arrow, + bool border_accepts_events); void SetBubbleArrow(views::BubbleBorder::Arrow arrow); @@ -49,7 +69,7 @@ class APP_LIST_EXPORT AppListView : public views::BubbleDelegateView, // InitAsBubble was called since the app list object needs to exist so that // it can set the host. void SetDragAndDropHostOfCurrentAppList( - app_list::ApplicationDragAndDropHost* drag_and_drop_host); + ApplicationDragAndDropHost* drag_and_drop_host); // Shows the UI when there are no pending icon loads. Otherwise, starts a // timer to show the UI when a maximum allowed wait time has expired. @@ -61,6 +81,7 @@ class APP_LIST_EXPORT AppListView : public views::BubbleDelegateView, // Overridden from views::View: virtual gfx::Size GetPreferredSize() OVERRIDE; + virtual void Paint(gfx::Canvas* canvas) OVERRIDE; // WidgetDelegate overrides: virtual bool ShouldHandleSystemCommands() const OVERRIDE; @@ -70,11 +91,27 @@ class APP_LIST_EXPORT AppListView : public views::BubbleDelegateView, // Invoked when the sign-in status is changed to switch on/off sign-in view. void OnSigninStatusChanged(); + void SetProfileByPath(const base::FilePath& profile_path); + + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + // Set a callback to be called the next time any app list paints. + static void SetNextPaintCallback(const base::Closure& callback); + #if defined(OS_WIN) HWND GetHWND() const; #endif + AppListModel* model() { return model_.get(); } + private: + void InitAsBubbleInternal(gfx::NativeView parent, + PaginationModel* pagination_model, + views::BubbleBorder::Arrow arrow, + bool border_accepts_events, + const gfx::Vector2d& anchor_offset); + // Overridden from views::WidgetDelegateView: virtual views::View* GetInitiallyFocusedView() OVERRIDE; virtual gfx::ImageSkia GetWindowIcon() OVERRIDE; @@ -92,8 +129,9 @@ class APP_LIST_EXPORT AppListView : public views::BubbleDelegateView, virtual void OnWidgetActivationChanged( views::Widget* widget, bool active) OVERRIDE; - // Overridden from SigninDelegateObserver: - virtual void OnSigninSuccess() OVERRIDE; + // Overridden from AppListModelObserver: + virtual void OnAppListModelSigninStatusChanged() OVERRIDE; + virtual void OnAppListModelUsersChanged() OVERRIDE; SigninDelegate* GetSigninDelegate(); @@ -103,6 +141,8 @@ class APP_LIST_EXPORT AppListView : public views::BubbleDelegateView, AppListMainView* app_list_main_view_; SigninView* signin_view_; + ObserverList<Observer> observers_; + DISALLOW_COPY_AND_ASSIGN(AppListView); }; diff --git a/chromium/ui/app_list/views/apps_grid_view.cc b/chromium/ui/app_list/views/apps_grid_view.cc index 1e9b2bfeda5..9135dda7344 100644 --- a/chromium/ui/app_list/views/apps_grid_view.cc +++ b/chromium/ui/app_list/views/apps_grid_view.cc @@ -7,15 +7,15 @@ #include <algorithm> #include "ui/app_list/app_list_item_model.h" -#include "ui/app_list/apps_grid_view_delegate.h" #include "ui/app_list/pagination_model.h" #include "ui/app_list/views/app_list_drag_and_drop_host.h" #include "ui/app_list/views/app_list_item_view.h" +#include "ui/app_list/views/apps_grid_view_delegate.h" #include "ui/app_list/views/page_switcher.h" #include "ui/app_list/views/pulsing_block_view.h" -#include "ui/base/animation/animation.h" -#include "ui/base/events/event.h" #include "ui/compositor/scoped_layer_animation_settings.h" +#include "ui/events/event.h" +#include "ui/gfx/animation/animation.h" #include "ui/views/border.h" #include "ui/views/view_model_utils.h" #include "ui/views/widget/widget.h" @@ -34,6 +34,8 @@ #include "ui/base/dragdrop/os_exchange_data_provider_win.h" #endif +namespace app_list { + namespace { // Distance a drag needs to be from the app grid to be considered 'outside', at @@ -66,7 +68,7 @@ const int kPrerenderPages = 1; const float kDragAndDropProxyScale = 1.5f; // For testing we remember the last created grid view. -app_list::AppsGridView* last_created_grid_view_for_test = NULL; +AppsGridView* last_created_grid_view_for_test = NULL; // RowMoveAnimationDelegate is used when moving an item into a different row. // Before running the animation, the item's layer is re-created and kept in @@ -86,8 +88,8 @@ class RowMoveAnimationDelegate } virtual ~RowMoveAnimationDelegate() {} - // ui::AnimationDelegate overrides: - virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE { + // gfx::AnimationDelegate overrides: + virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE { view_->layer()->SetOpacity(animation->GetCurrentValue()); view_->layer()->ScheduleDraw(); @@ -98,11 +100,11 @@ class RowMoveAnimationDelegate layer_->ScheduleDraw(); } } - virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE { + virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE { view_->layer()->SetOpacity(1.0f); view_->layer()->ScheduleDraw(); } - virtual void AnimationCanceled(const ui::Animation* animation) OVERRIDE { + virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE { view_->layer()->SetOpacity(1.0f); view_->layer()->ScheduleDraw(); } @@ -120,8 +122,6 @@ class RowMoveAnimationDelegate } // namespace -namespace app_list { - #if defined(OS_WIN) && !defined(USE_AURA) // Interprets drag events sent from Windows via the drag/drop API and forwards // them to AppsGridView. @@ -134,16 +134,15 @@ namespace app_list { // Windows drag that never enters the synchronous drag phase. class SynchronousDrag : public ui::DragSourceWin { public: - SynchronousDrag(app_list::AppsGridView* grid_view, - app_list::AppListItemView* drag_view, - const gfx::Point& drag_view_offset) + SynchronousDrag(AppsGridView* grid_view, + AppListItemView* drag_view, + const gfx::Point& drag_view_offset) : grid_view_(grid_view), drag_view_(drag_view), drag_view_offset_(drag_view_offset), has_shortcut_path_(false), running_(false), - canceled_(false) { - } + canceled_(false) {} void set_shortcut_path(const base::FilePath& shortcut_path) { has_shortcut_path_ = true; @@ -187,8 +186,7 @@ class SynchronousDrag : public ui::DragSourceWin { } virtual void OnDragSourceMove() OVERRIDE { - grid_view_->UpdateDrag(app_list::AppsGridView::MOUSE, - GetCursorInGridViewCoords()); + grid_view_->UpdateDrag(AppsGridView::MOUSE, GetCursorInGridViewCoords()); } void SetupExchangeData(ui::OSExchangeData* data) { @@ -221,8 +219,8 @@ class SynchronousDrag : public ui::DragSourceWin { return grid_view_pt; } - app_list::AppsGridView* grid_view_; - app_list::AppListItemView* drag_view_; + AppsGridView* grid_view_; + AppListItemView* drag_view_; gfx::Point drag_view_offset_; bool has_shortcut_path_; base::FilePath shortcut_path_; @@ -256,6 +254,13 @@ AppsGridView::AppsGridView(AppsGridViewDelegate* delegate, } AppsGridView::~AppsGridView() { + // Coming here |drag_view_| should already be canceled since otherwise the + // drag would disappear after the app list got animated away and closed, + // which would look odd. + DCHECK(!drag_view_); + if (drag_view_) + EndDrag(true); + if (model_) { model_->RemoveObserver(this); model_->apps()->RemoveObserver(this); @@ -347,9 +352,12 @@ void AppsGridView::OnGotShortcutPath(const base::FilePath& path) { void AppsGridView::StartSettingUpSynchronousDrag() { #if defined(OS_WIN) && !defined(USE_AURA) + if (!delegate_) + return; + delegate_->GetShortcutPathForApp( - drag_view_->model()->app_id(), - base::Bind(&AppsGridView::OnGotShortcutPath, base::Unretained(this))); + drag_view_->model()->app_id(), + base::Bind(&AppsGridView::OnGotShortcutPath, base::Unretained(this))); synchronous_drag_ = new SynchronousDrag(this, drag_view_, drag_view_offset_); #endif } @@ -431,7 +439,8 @@ void AppsGridView::EndDrag(bool cancel) { // EndDrag was called before if |drag_view_| is NULL. if (!drag_view_) return; - + // Coming here a drag and drop was in progress. + bool landed_in_drag_and_drop_host = forward_events_to_drag_and_drop_host_; if (forward_events_to_drag_and_drop_host_) { forward_events_to_drag_and_drop_host_ = false; drag_and_drop_host_->EndDrag(cancel); @@ -445,7 +454,17 @@ void AppsGridView::EndDrag(bool cancel) { // If we had a drag and drop proxy icon, we delete it and make the real // item visible again. drag_and_drop_host_->DestroyDragIconProxy(); - HideView(drag_view_, false); + if (landed_in_drag_and_drop_host) { + // Move the item directly to the target location, avoiding the "zip back" + // animation if the user was pinning it to the shelf. + int i = drop_target_.slot; + gfx::Rect bounds = view_model_.ideal_bounds(i); + drag_view_->SetBoundsRect(bounds); + } + // Fade in slowly if it landed in the shelf. + SetViewHidden(drag_view_, + false /* hide */, + !landed_in_drag_and_drop_host /* animate */); } // The drag can be ended after the synchronous drag is created but before it @@ -969,7 +988,9 @@ void AppsGridView::StartDragAndDropHostDrag(const gfx::Point& grid_location) { drag_view_, delta, kDragAndDropProxyScale); - HideView(drag_view_, true); + SetViewHidden(drag_view_, + true /* hide */, + true /* no animation */); } void AppsGridView::DispatchDragEventToDragAndDropHost( @@ -1170,10 +1191,12 @@ void AppsGridView::OnAppListModelStatusChanged() { SchedulePaint(); } -void AppsGridView::HideView(views::View* view, bool hide) { +void AppsGridView::SetViewHidden(views::View* view, bool hide, bool immediate) { #if defined(USE_AURA) ui::ScopedLayerAnimationSettings animator(view->layer()->GetAnimator()); - animator.SetPreemptionStrategy(ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET); + animator.SetPreemptionStrategy( + immediate ? ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET : + ui::LayerAnimator::BLEND_WITH_CURRENT_ANIMATION); view->layer()->SetOpacity(hide ? 0 : 1); #endif } diff --git a/chromium/ui/app_list/views/apps_grid_view.h b/chromium/ui/app_list/views/apps_grid_view.h index 9c201641f15..2b7b51d0b88 100644 --- a/chromium/ui/app_list/views/apps_grid_view.h +++ b/chromium/ui/app_list/views/apps_grid_view.h @@ -135,7 +135,7 @@ class APP_LIST_EXPORT AppsGridView : public views::View, } private: - friend class app_list::test::AppsGridViewTestApi; + friend class test::AppsGridViewTestApi; // Represents the index to an item view in the grid. struct Index { @@ -246,8 +246,10 @@ class APP_LIST_EXPORT AppsGridView : public views::View, virtual void OnAppListModelStatusChanged() OVERRIDE; // Hide a given view temporarily without losing (mouse) events and / or - // changing the size of it. - void HideView(views::View* view, bool hide); + // changing the size of it. If |immediate| is set the change will be + // immediately applied - otherwise it will change gradually. + // If |hide| is set the view will get hidden, otherwise it gets shown. + void SetViewHidden(views::View* view, bool hide, bool immediate); AppListModel* model_; // Owned by AppListView. AppsGridViewDelegate* delegate_; diff --git a/chromium/ui/app_list/apps_grid_view_delegate.h b/chromium/ui/app_list/views/apps_grid_view_delegate.h index 59dc8f66fb2..83430b0fa40 100644 --- a/chromium/ui/app_list/apps_grid_view_delegate.h +++ b/chromium/ui/app_list/views/apps_grid_view_delegate.h @@ -1,9 +1,9 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// 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. -#ifndef UI_APP_LIST_APPS_GRID_VIEW_DELEGATE_H_ -#define UI_APP_LIST_APPS_GRID_VIEW_DELEGATE_H_ +#ifndef UI_APP_LIST_VIEWS_APPS_GRID_VIEW_DELEGATE_H_ +#define UI_APP_LIST_VIEWS_APPS_GRID_VIEW_DELEGATE_H_ #include "base/callback_forward.h" #include "ui/app_list/app_list_export.h" @@ -34,4 +34,4 @@ class APP_LIST_EXPORT AppsGridViewDelegate { } // namespace app_list -#endif // UI_APP_LIST_APPS_GRID_VIEW_DELEGATE_H_ +#endif // UI_APP_LIST_VIEWS_APPS_GRID_VIEW_DELEGATE_H_ diff --git a/chromium/ui/app_list/views/apps_grid_view_unittest.cc b/chromium/ui/app_list/views/apps_grid_view_unittest.cc index 87d5f672c12..9e0cc5c0340 100644 --- a/chromium/ui/app_list/views/apps_grid_view_unittest.cc +++ b/chromium/ui/app_list/views/apps_grid_view_unittest.cc @@ -10,6 +10,7 @@ #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" +#include "base/strings/utf_string_conversions.h" #include "base/timer/timer.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/app_list/app_list_item_model.h" @@ -47,10 +48,14 @@ class PageFlipWaiter : public PaginationModelObserver { DCHECK(!wait_); wait_ = true; page_changed_ = false; - wait_timer_.Stop(); - wait_timer_.Start(FROM_HERE, - base::TimeDelta::FromMilliseconds(time_out_ms), - this, &PageFlipWaiter::OnWaitTimeOut); + + if (time_out_ms) { + wait_timer_.Stop(); + wait_timer_.Start(FROM_HERE, + base::TimeDelta::FromMilliseconds(time_out_ms), + this, &PageFlipWaiter::OnWaitTimeOut); + } + ui_loop_->Run(); wait_ = false; return page_changed_; @@ -260,15 +265,7 @@ TEST_F(AppsGridViewTest, MouseDrag) { test_api_->LayoutToIdealBounds(); } -// Test fails sometimes on chrome os. -// http://crbug.com/242248 -#if defined(OS_CHROMEOS) -#define MAYBE_MouseDragFlipPage DISABLED_MouseDragFlipPage -#else -#define MAYBE_MouseDragFlipPage MouseDragFlipPage -#endif // defined(OS_CHROMEOS) - -TEST_F(AppsGridViewTest, MAYBE_MouseDragFlipPage) { +TEST_F(AppsGridViewTest, MouseDragFlipPage) { test_api_->SetPageFlipDelay(10); pagination_model_->SetTransitionDurations(10, 10); @@ -288,11 +285,11 @@ TEST_F(AppsGridViewTest, MAYBE_MouseDragFlipPage) { SimulateDrag(AppsGridView::MOUSE, from, to); // Page should be flipped after sometime. - EXPECT_TRUE(page_flip_waiter.Wait(100)); + EXPECT_TRUE(page_flip_waiter.Wait(0)); EXPECT_EQ(1, pagination_model_->selected_page()); // Stay there and page should be flipped again. - EXPECT_TRUE(page_flip_waiter.Wait(100)); + EXPECT_TRUE(page_flip_waiter.Wait(0)); EXPECT_EQ(2, pagination_model_->selected_page()); // Stay there longer and no page flip happen since we are at the last page. @@ -306,10 +303,10 @@ TEST_F(AppsGridViewTest, MAYBE_MouseDragFlipPage) { SimulateDrag(AppsGridView::MOUSE, from, to); - EXPECT_TRUE(page_flip_waiter.Wait(100)); + EXPECT_TRUE(page_flip_waiter.Wait(0)); EXPECT_EQ(1, pagination_model_->selected_page()); - EXPECT_TRUE(page_flip_waiter.Wait(100)); + EXPECT_TRUE(page_flip_waiter.Wait(0)); EXPECT_EQ(0, pagination_model_->selected_page()); EXPECT_FALSE(page_flip_waiter.Wait(100)); @@ -428,5 +425,37 @@ TEST_F(AppsGridViewTest, HighlightWithKeyboard) { first_index_on_page2))); } +TEST_F(AppsGridViewTest, ItemLabelShortNameOverride) { + // If the app's full name and short name differ, the title label's tooltip + // should always be the full name of the app. + std::string expected_text("xyz"); + std::string expected_tooltip("tooltip"); + model_->AddItem(expected_text, expected_tooltip); + + string16 actual_tooltip; + AppListItemView* item_view = GetItemViewAt(0); + ASSERT_TRUE(item_view); + const views::Label* title_label = item_view->title(); + EXPECT_TRUE(title_label->GetTooltipText( + title_label->bounds().CenterPoint(), &actual_tooltip)); + EXPECT_EQ(expected_tooltip, UTF16ToUTF8(actual_tooltip)); + EXPECT_EQ(expected_text, UTF16ToUTF8(title_label->text())); +} + +TEST_F(AppsGridViewTest, ItemLabelNoShortName) { + // If the app's full name and short name are the same, use the default tooltip + // behavior of the label (only show a tooltip if the title is truncated). + std::string title("a"); + model_->AddItem(title, title); + + string16 actual_tooltip; + AppListItemView* item_view = GetItemViewAt(0); + ASSERT_TRUE(item_view); + const views::Label* title_label = item_view->title(); + EXPECT_FALSE(title_label->GetTooltipText( + title_label->bounds().CenterPoint(), &actual_tooltip)); + EXPECT_EQ(title, UTF16ToUTF8(title_label->text())); +} + } // namespace test } // namespace app_list diff --git a/chromium/ui/app_list/views/contents_view.cc b/chromium/ui/app_list/views/contents_view.cc index 5211eb1e6d7..3ecc276b75f 100644 --- a/chromium/ui/app_list/views/contents_view.cc +++ b/chromium/ui/app_list/views/contents_view.cc @@ -12,7 +12,7 @@ #include "ui/app_list/views/app_list_main_view.h" #include "ui/app_list/views/apps_grid_view.h" #include "ui/app_list/views/search_result_list_view.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" #include "ui/views/animation/bounds_animator.h" #include "ui/views/view_model.h" #include "ui/views/view_model_utils.h" @@ -76,8 +76,13 @@ ContentsView::ContentsView(AppListMainView* app_list_main_view, ContentsView::~ContentsView() { } +void ContentsView::CancelDrag() { + if (apps_grid_view_ && apps_grid_view_->has_dragged_view()) + apps_grid_view_->EndDrag(true); +} + void ContentsView::SetDragAndDropHostOfCurrentAppList( - app_list::ApplicationDragAndDropHost* drag_and_drop_host) { + ApplicationDragAndDropHost* drag_and_drop_host) { apps_grid_view_->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host); } diff --git a/chromium/ui/app_list/views/contents_view.h b/chromium/ui/app_list/views/contents_view.h index f0b974cf12b..b9447734b50 100644 --- a/chromium/ui/app_list/views/contents_view.h +++ b/chromium/ui/app_list/views/contents_view.h @@ -34,10 +34,13 @@ class ContentsView : public views::View { AppListModel* model); virtual ~ContentsView(); + // The app list gets closed and drag and drop operations need to be cancelled. + void CancelDrag(); + // If |drag_and_drop| is not NULL it will be called upon drag and drop // operations outside the application list. void SetDragAndDropHostOfCurrentAppList( - app_list::ApplicationDragAndDropHost* drag_and_drop_host); + ApplicationDragAndDropHost* drag_and_drop_host); void ShowSearchResults(bool show); diff --git a/chromium/ui/app_list/views/page_switcher.cc b/chromium/ui/app_list/views/page_switcher.cc index 665b0230713..99e9749d154 100644 --- a/chromium/ui/app_list/views/page_switcher.cc +++ b/chromium/ui/app_list/views/page_switcher.cc @@ -9,12 +9,14 @@ #include "third_party/skia/include/core/SkPath.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/pagination_model.h" -#include "ui/base/animation/throb_animation.h" +#include "ui/gfx/animation/throb_animation.h" #include "ui/gfx/canvas.h" #include "ui/gfx/skia_util.h" #include "ui/views/controls/button/custom_button.h" #include "ui/views/layout/box_layout.h" +namespace app_list { + namespace { const int kPreferredHeight = 57; @@ -52,11 +54,10 @@ class PageSwitcherButton : public views::CustomButton { } virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { - if (state() == STATE_HOVERED) { - PaintButton(canvas, app_list::kPagerHoverColor); - } else { - PaintButton(canvas, app_list::kPagerNormalColor); - } + if (state() == STATE_HOVERED) + PaintButton(canvas, kPagerHoverColor); + else + PaintButton(canvas, kPagerNormalColor); } private: @@ -94,7 +95,7 @@ class PageSwitcherButton : public views::CustomButton { selected_path.addRoundRect(gfx::RectToSkRect(selected_rect), SkIntToScalar(kButtonCornerRadius), SkIntToScalar(kButtonCornerRadius)); - paint.setColor(app_list::kPagerSelectedColor); + paint.setColor(kPagerSelectedColor); canvas->DrawPath(selected_path, paint); } } @@ -116,8 +117,6 @@ PageSwitcherButton* GetButtonByIndex(views::View* buttons, int index) { } // namespace -namespace app_list { - PageSwitcher::PageSwitcher(PaginationModel* model) : model_(model), buttons_(new views::View) { diff --git a/chromium/ui/app_list/views/search_box_view.cc b/chromium/ui/app_list/views/search_box_view.cc index 1d997e5e7ef..9b96d3eec0a 100644 --- a/chromium/ui/app_list/views/search_box_view.cc +++ b/chromium/ui/app_list/views/search_box_view.cc @@ -9,10 +9,10 @@ #include "grit/ui_resources.h" #include "ui/app_list/app_list_model.h" #include "ui/app_list/search_box_model.h" -#include "ui/app_list/search_box_view_delegate.h" #include "ui/app_list/views/app_list_menu_views.h" -#include "ui/base/events/event.h" +#include "ui/app_list/views/search_box_view_delegate.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/events/event.h" #include "ui/views/controls/button/menu_button.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/textfield/textfield.h" @@ -40,7 +40,7 @@ SearchBoxView::SearchBoxView(SearchBoxViewDelegate* delegate, AppListModel* model) : delegate_(delegate), view_delegate_(view_delegate), - model_(model->search_box()), + model_(model), icon_view_(new views::ImageView), search_box_(new views::Textfield), contents_view_(NULL) { @@ -65,13 +65,13 @@ SearchBoxView::SearchBoxView(SearchBoxViewDelegate* delegate, search_box_->SetController(this); AddChildView(search_box_); - model_->AddObserver(this); + model_->search_box()->AddObserver(this); IconChanged(); HintTextChanged(); } SearchBoxView::~SearchBoxView() { - model_->RemoveObserver(this); + model_->search_box()->RemoveObserver(this); } bool SearchBoxView::HasSearch() const { @@ -132,10 +132,10 @@ bool SearchBoxView::OnMouseWheel(const ui::MouseWheelEvent& event) { void SearchBoxView::UpdateModel() { // Temporarily remove from observer to ignore notifications caused by us. - model_->RemoveObserver(this); - model_->SetText(search_box_->text()); - model_->SetSelectionModel(search_box_->GetSelectionModel()); - model_->AddObserver(this); + model_->search_box()->RemoveObserver(this); + model_->search_box()->SetText(search_box_->text()); + model_->search_box()->SetSelectionModel(search_box_->GetSelectionModel()); + model_->search_box()->AddObserver(this); } void SearchBoxView::NotifyQueryChanged() { @@ -160,7 +160,7 @@ bool SearchBoxView::HandleKeyEvent(views::Textfield* sender, void SearchBoxView::OnMenuButtonClicked(View* source, const gfx::Point& point) { if (!menu_) - menu_.reset(new AppListMenuViews(view_delegate_)); + menu_.reset(new AppListMenuViews(view_delegate_, model_)); const gfx::Point menu_location = menu_button_->GetBoundsInScreen().bottom_right() + @@ -169,19 +169,20 @@ void SearchBoxView::OnMenuButtonClicked(View* source, const gfx::Point& point) { } void SearchBoxView::IconChanged() { - icon_view_->SetImage(model_->icon()); + icon_view_->SetImage(model_->search_box()->icon()); } void SearchBoxView::HintTextChanged() { - search_box_->set_placeholder_text(model_->hint_text()); + search_box_->set_placeholder_text(model_->search_box()->hint_text()); } void SearchBoxView::SelectionModelChanged() { - search_box_->SelectSelectionModel(model_->selection_model()); + search_box_->SelectSelectionModel(model_->search_box()->selection_model()); } void SearchBoxView::TextChanged() { - search_box_->SetText(model_->text()); + search_box_->SetText(model_->search_box()->text()); + NotifyQueryChanged(); } } // namespace app_list diff --git a/chromium/ui/app_list/views/search_box_view.h b/chromium/ui/app_list/views/search_box_view.h index 439a4cf291b..c06990262a5 100644 --- a/chromium/ui/app_list/views/search_box_view.h +++ b/chromium/ui/app_list/views/search_box_view.h @@ -21,8 +21,8 @@ class Textfield; namespace app_list { class AppListMenuViews; -class AppListViewDelegate; class AppListModel; +class AppListViewDelegate; class SearchBoxModel; class SearchBoxViewDelegate; @@ -80,7 +80,7 @@ class SearchBoxView : public views::View, SearchBoxViewDelegate* delegate_; // Not owned. AppListViewDelegate* view_delegate_; // Not owned. - SearchBoxModel* model_; // Owned by AppListModel. + AppListModel* model_; // Owned by AppListView. scoped_ptr<AppListMenuViews> menu_; diff --git a/chromium/ui/app_list/search_box_view_delegate.h b/chromium/ui/app_list/views/search_box_view_delegate.h index df5d2b41e09..cdbf23878bb 100644 --- a/chromium/ui/app_list/search_box_view_delegate.h +++ b/chromium/ui/app_list/views/search_box_view_delegate.h @@ -1,9 +1,9 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// 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. -#ifndef UI_APP_LIST_SEARCH_BOX_VIEW_DELEGATE_H_ -#define UI_APP_LIST_SEARCH_BOX_VIEW_DELEGATE_H_ +#ifndef UI_APP_LIST_VIEWS_SEARCH_BOX_VIEW_DELEGATE_H_ +#define UI_APP_LIST_VIEWS_SEARCH_BOX_VIEW_DELEGATE_H_ #include "ui/app_list/app_list_export.h" @@ -22,4 +22,4 @@ class APP_LIST_EXPORT SearchBoxViewDelegate { } // namespace app_list -#endif // UI_APP_LIST_SEARCH_BOX_VIEW_DELEGATE_H_ +#endif // UI_APP_LIST_VIEWS_SEARCH_BOX_VIEW_DELEGATE_H_ diff --git a/chromium/ui/app_list/views/search_result_list_view.cc b/chromium/ui/app_list/views/search_result_list_view.cc index 5eaad3c688f..3387cecad10 100644 --- a/chromium/ui/app_list/views/search_result_list_view.cc +++ b/chromium/ui/app_list/views/search_result_list_view.cc @@ -8,9 +8,9 @@ #include "base/bind.h" #include "base/message_loop/message_loop.h" -#include "ui/app_list/search_result_list_view_delegate.h" +#include "ui/app_list/views/search_result_list_view_delegate.h" #include "ui/app_list/views/search_result_view.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" #include "ui/views/layout/box_layout.h" namespace { diff --git a/chromium/ui/app_list/search_result_list_view_delegate.h b/chromium/ui/app_list/views/search_result_list_view_delegate.h index e45ac4b3bc7..405094b31a5 100644 --- a/chromium/ui/app_list/search_result_list_view_delegate.h +++ b/chromium/ui/app_list/views/search_result_list_view_delegate.h @@ -1,9 +1,9 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// 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. -#ifndef UI_APP_LIST_SEARCH_RESULT_LIST_VIEW_DELEGATE_H_ -#define UI_APP_LIST_SEARCH_RESULT_LIST_VIEW_DELEGATE_H_ +#ifndef UI_APP_LIST_VIEWS_SEARCH_RESULT_LIST_VIEW_DELEGATE_H_ +#define UI_APP_LIST_VIEWS_SEARCH_RESULT_LIST_VIEW_DELEGATE_H_ #include "ui/app_list/app_list_export.h" @@ -37,4 +37,4 @@ class APP_LIST_EXPORT SearchResultListViewDelegate { } // namespace app_list -#endif // UI_APP_LIST_SEARCH_RESULT_LIST_VIEW_DELEGATE_H_ +#endif // UI_APP_LIST_VIEWS_SEARCH_RESULT_LIST_VIEW_DELEGATE_H_ diff --git a/chromium/ui/app_list/views/search_result_view.cc b/chromium/ui/app_list/views/search_result_view.cc index 55b9e0b653d..9e7fe51f648 100644 --- a/chromium/ui/app_list/views/search_result_view.cc +++ b/chromium/ui/app_list/views/search_result_view.cc @@ -20,6 +20,8 @@ #include "ui/views/controls/menu/menu_item_view.h" #include "ui/views/controls/menu/menu_runner.h" +namespace app_list { + namespace { const int kPreferredWidth = 300; @@ -36,24 +38,24 @@ const int kActionButtonRightMargin = 8; // Creates a RenderText of given |text| and |styles|. Caller takes ownership // of returned RenderText. gfx::RenderText* CreateRenderText(const base::string16& text, - const app_list::SearchResult::Tags& tags) { + const SearchResult::Tags& tags) { gfx::RenderText* render_text = gfx::RenderText::CreateInstance(); render_text->SetText(text); - render_text->SetColor(app_list::kResultDefaultTextColor); + render_text->SetColor(kResultDefaultTextColor); - for (app_list::SearchResult::Tags::const_iterator it = tags.begin(); + for (SearchResult::Tags::const_iterator it = tags.begin(); it != tags.end(); ++it) { // NONE means default style so do nothing. - if (it->styles == app_list::SearchResult::Tag::NONE) + if (it->styles == SearchResult::Tag::NONE) continue; - if (it->styles & app_list::SearchResult::Tag::MATCH) + if (it->styles & SearchResult::Tag::MATCH) render_text->ApplyStyle(gfx::BOLD, true, it->range); - if (it->styles & app_list::SearchResult::Tag::DIM) - render_text->ApplyColor(app_list::kResultDimmedTextColor, it->range); - else if (it->styles & app_list::SearchResult::Tag::URL) - render_text->ApplyColor(app_list::kResultURLTextColor, it->range); + if (it->styles & SearchResult::Tag::DIM) + render_text->ApplyColor(kResultDimmedTextColor, it->range); + else if (it->styles & SearchResult::Tag::URL) + render_text->ApplyColor(kResultURLTextColor, it->range); } return render_text; @@ -61,8 +63,6 @@ gfx::RenderText* CreateRenderText(const base::string16& text, } // namespace -namespace app_list { - // static const char SearchResultView::kViewClassName[] = "ui/app_list/SearchResultView"; diff --git a/chromium/ui/aura/aura.gyp b/chromium/ui/aura/aura.gyp index a4fe8612de6..c2983e921a6 100644 --- a/chromium/ui/aura/aura.gyp +++ b/chromium/ui/aura/aura.gyp @@ -83,19 +83,13 @@ 'remote_root_window_host_win.h', 'root_window_host.h', 'root_window_host_delegate.h', - 'root_window_host_mac.h', - 'root_window_host_mac.mm', 'root_window_host_ozone.cc', 'root_window_host_ozone.h', 'root_window_host_win.cc', 'root_window_host_win.h', 'root_window_host_x11.cc', 'root_window_host_x11.h', - 'root_window_mac.h', - 'root_window_mac.mm', 'root_window_transformer.h', - 'root_window_view_mac.h', - 'root_window_view_mac.mm', 'root_window.cc', 'root_window.h', 'window.cc', @@ -106,12 +100,6 @@ 'window_tracker.h', ], 'conditions': [ - ['OS=="mac"', { - 'sources/': [ - ['exclude', 'client/dispatcher_client.cc'], - ['exclude', 'client/dispatcher_client.h'], - ], - }], ['use_x11==1', { 'link_settings': { 'libraries': [ @@ -181,6 +169,7 @@ 'target_name': 'aura_test_support_pak', 'type': 'none', 'dependencies': [ + '<(DEPTH)/ui/base/strings/ui_strings.gyp:ui_strings', '<(DEPTH)/ui/ui.gyp:ui_resources', ], 'variables': { @@ -191,6 +180,7 @@ 'action_name': 'repack_aura_test_support_pack', 'variables': { 'pak_inputs': [ + '<(SHARED_INTERMEDIATE_DIR)/ui/app_locale_settings/app_locale_settings_en-US.pak', '<(SHARED_INTERMEDIATE_DIR)/ui/ui_resources/ui_resources_100_percent.pak', ], }, diff --git a/chromium/ui/aura/bench/DEPS b/chromium/ui/aura/bench/DEPS index 69deb976808..1fda55436bc 100644 --- a/chromium/ui/aura/bench/DEPS +++ b/chromium/ui/aura/bench/DEPS @@ -1,4 +1,5 @@ include_rules = [ + "+cc", "+third_party/khronos", "+third_party/WebKit/public/platform", ] diff --git a/chromium/ui/aura/bench/bench_main.cc b/chromium/ui/aura/bench/bench_main.cc index aee7e79c83a..f344854ea1a 100644 --- a/chromium/ui/aura/bench/bench_main.cc +++ b/chromium/ui/aura/bench/bench_main.cc @@ -10,6 +10,7 @@ #include "base/message_loop/message_loop.h" #include "base/strings/string_split.h" #include "base/time/time.h" +#include "cc/output/context_provider.h" #include "third_party/khronos/GLES2/gl2.h" #include "third_party/skia/include/core/SkXfermode.h" #include "ui/aura/client/default_capture_client.h" @@ -35,7 +36,7 @@ #include "third_party/khronos/GLES2/gl2ext.h" #if defined(USE_X11) -#include "base/message_loop/message_pump_aurax11.h" +#include "base/message_loop/message_pump_x11.h" #endif using base::TimeTicks; @@ -181,7 +182,7 @@ class WebGLBench : public BenchCompositorObserver { parent_(parent), webgl_(ui::LAYER_TEXTURED), compositor_(compositor), - context_(), + context_provider_(), texture_(), fbo_(0), do_draw_(true) { @@ -207,24 +208,26 @@ class WebGLBench : public BenchCompositorObserver { webgl_.SetBounds(bounds); parent_->Add(&webgl_); - context_ = ui::ContextFactory::GetInstance()->CreateOffscreenContext(); - context_->makeContextCurrent(); - texture_ = new WebGLTexture(context_.get(), bounds.size()); - fbo_ = context_->createFramebuffer(); + context_provider_ = ui::ContextFactory::GetInstance() + ->OffscreenContextProviderForMainThread(); + WebKit::WebGraphicsContext3D* context = context_provider_->Context3d(); + context->makeContextCurrent(); + texture_ = new WebGLTexture(context, bounds.size()); + fbo_ = context->createFramebuffer(); compositor->AddObserver(this); webgl_.SetExternalTexture(texture_.get()); - context_->bindFramebuffer(GL_FRAMEBUFFER, fbo_); - context_->framebufferTexture2D( + context->bindFramebuffer(GL_FRAMEBUFFER, fbo_); + context->framebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_->PrepareTexture(), 0); - context_->clearColor(0.f, 1.f, 0.f, 1.f); - context_->clear(GL_COLOR_BUFFER_BIT); - context_->flush(); + context->clearColor(0.f, 1.f, 0.f, 1.f); + context->clear(GL_COLOR_BUFFER_BIT); + context->flush(); } virtual ~WebGLBench() { - context_->makeContextCurrent(); - context_->deleteFramebuffer(fbo_); + context_provider_->Context3d()->makeContextCurrent(); + context_provider_->Context3d()->deleteFramebuffer(fbo_); webgl_.SetExternalTexture(NULL); texture_ = NULL; compositor_->RemoveObserver(this); @@ -232,10 +235,11 @@ class WebGLBench : public BenchCompositorObserver { virtual void Draw() OVERRIDE { if (do_draw_) { - context_->makeContextCurrent(); - context_->clearColor((frames() % kFrames)*1.0/kFrames, 1.f, 0.f, 1.f); - context_->clear(GL_COLOR_BUFFER_BIT); - context_->flush(); + WebKit::WebGraphicsContext3D* context = context_provider_->Context3d(); + context->makeContextCurrent(); + context->clearColor((frames() % kFrames)*1.0/kFrames, 1.f, 0.f, 1.f); + context->clear(GL_COLOR_BUFFER_BIT); + context->flush(); } webgl_.SetExternalTexture(texture_.get()); webgl_.SchedulePaint(gfx::Rect(webgl_.bounds().size())); @@ -246,7 +250,7 @@ class WebGLBench : public BenchCompositorObserver { Layer* parent_; Layer webgl_; Compositor* compositor_; - scoped_ptr<WebGraphicsContext3D> context_; + scoped_refptr<cc::ContextProvider> context_provider_; scoped_refptr<WebGLTexture> texture_; // The FBO that is used to render to the texture. @@ -296,8 +300,12 @@ int main(int argc, char** argv) { base::AtExitManager exit_manager; + // The ContextFactory must exist before any Compositors are created. + bool allow_test_contexts = false; + ui::Compositor::InitializeContextFactoryForTests(allow_test_contexts); + ui::RegisterPathProvider(); - icu_util::Initialize(); + base::i18n::InitializeICU(); ResourceBundle::InitSharedInstanceWithLocale("en-US", NULL); base::MessageLoop message_loop(base::MessageLoop::TYPE_UI); diff --git a/chromium/ui/aura/client/cursor_client.h b/chromium/ui/aura/client/cursor_client.h index acdf255b850..e8740ac1704 100644 --- a/chromium/ui/aura/client/cursor_client.h +++ b/chromium/ui/aura/client/cursor_client.h @@ -7,6 +7,7 @@ #include "base/strings/string16.h" #include "ui/aura/aura_export.h" +#include "ui/base/cursor/cursor.h" #include "ui/gfx/native_widget_types.h" namespace gfx { @@ -34,6 +35,9 @@ class AURA_EXPORT CursorClient { // Sets the scale of the mouse cursor icon. virtual void SetScale(float scale) = 0; + // Sets the type of the mouse cursor icon. + virtual void SetCursorSet(ui::CursorSetType cursor_set) = 0; + // Gets whether the cursor is visible. virtual bool IsCursorVisible() const = 0; @@ -60,6 +64,9 @@ class AURA_EXPORT CursorClient { // EnableMouseEvents/DisableMouseEvents. virtual void UnlockCursor() = 0; + // Returns true if the cursor is locked. + virtual bool IsCursorLocked() const = 0; + // Used to add or remove a CursorClientObserver. virtual void AddObserver(CursorClientObserver* observer) = 0; virtual void RemoveObserver(CursorClientObserver* observer) = 0; diff --git a/chromium/ui/aura/demo/demo_main.cc b/chromium/ui/aura/demo/demo_main.cc index 06938d87419..dbf1c80b7a6 100644 --- a/chromium/ui/aura/demo/demo_main.cc +++ b/chromium/ui/aura/demo/demo_main.cc @@ -16,15 +16,16 @@ #include "ui/aura/test/test_screen.h" #include "ui/aura/window.h" #include "ui/aura/window_delegate.h" -#include "ui/base/events/event.h" #include "ui/base/hit_test.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_base_paths.h" +#include "ui/compositor/compositor.h" +#include "ui/events/event.h" #include "ui/gfx/canvas.h" #include "ui/gfx/rect.h" #if defined(USE_X11) -#include "base/message_loop/message_pump_aurax11.h" +#include "base/message_loop/message_pump_x11.h" #endif namespace { @@ -67,9 +68,8 @@ class DemoWindowDelegate : public aura::WindowDelegate { virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {} virtual bool HasHitTestMask() const OVERRIDE { return false; } virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {} - virtual scoped_refptr<ui::Texture> CopyTexture() OVERRIDE { - return scoped_refptr<ui::Texture>(); - } + virtual void DidRecreateLayer(ui::Layer* old_layer, + ui::Layer* new_layer) OVERRIDE {} private: SkColor color_; @@ -110,6 +110,11 @@ class DemoStackingClient : public aura::client::StackingClient { int DemoMain() { // Create the message-loop here before creating the root window. base::MessageLoop message_loop(base::MessageLoop::TYPE_UI); + + // The ContextFactory must exist before any Compositors are created. + bool allow_test_contexts = false; + ui::Compositor::InitializeContextFactoryForTests(allow_test_contexts); + aura::Env::GetInstance(); scoped_ptr<aura::TestScreen> test_screen(aura::TestScreen::Create()); gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen.get()); @@ -160,7 +165,7 @@ int main(int argc, char** argv) { base::AtExitManager exit_manager; ui::RegisterPathProvider(); - icu_util::Initialize(); + base::i18n::InitializeICU(); ResourceBundle::InitSharedInstanceWithLocale("en-US", NULL); return DemoMain(); diff --git a/chromium/ui/aura/device_list_updater_aurax11.cc b/chromium/ui/aura/device_list_updater_aurax11.cc index 0671dfecbfd..8240cb495c3 100644 --- a/chromium/ui/aura/device_list_updater_aurax11.cc +++ b/chromium/ui/aura/device_list_updater_aurax11.cc @@ -6,7 +6,7 @@ #include <X11/extensions/XInput2.h> -#include "ui/base/events/event_utils.h" +#include "ui/events/event_utils.h" namespace aura { diff --git a/chromium/ui/aura/env.cc b/chromium/ui/aura/env.cc index 6b2b3e023a3..a4cf8151e24 100644 --- a/chromium/ui/aura/env.cc +++ b/chromium/ui/aura/env.cc @@ -12,7 +12,7 @@ #include "ui/compositor/compositor_switches.h" #if defined(USE_X11) -#include "base/message_loop/message_pump_aurax11.h" +#include "base/message_loop/message_pump_x11.h" #endif namespace aura { @@ -30,7 +30,7 @@ Env::Env() Env::~Env() { #if defined(USE_X11) - base::MessagePumpAuraX11::Current()->RemoveObserver( + base::MessagePumpX11::Current()->RemoveObserver( &device_list_updater_aurax11_); #endif @@ -62,15 +62,13 @@ void Env::RemoveObserver(EnvObserver* observer) { observers_.RemoveObserver(observer); } -#if !defined(OS_MACOSX) base::MessageLoop::Dispatcher* Env::GetDispatcher() { #if defined(USE_X11) - return base::MessagePumpAuraX11::Current(); + return base::MessagePumpX11::Current(); #else return dispatcher_.get(); #endif } -#endif void Env::RootWindowActivated(RootWindow* root_window) { FOR_EACH_OBSERVER(EnvObserver, observers_, @@ -87,7 +85,7 @@ void Env::Init() { #if defined(USE_X11) // We can't do this with a root window listener because XI_HierarchyChanged // messages don't have a target window. - base::MessagePumpAuraX11::Current()->AddObserver( + base::MessagePumpX11::Current()->AddObserver( &device_list_updater_aurax11_); #endif ui::Compositor::Initialize(); diff --git a/chromium/ui/aura/env.h b/chromium/ui/aura/env.h index ad31cd57ac5..c52b892d573 100644 --- a/chromium/ui/aura/env.h +++ b/chromium/ui/aura/env.h @@ -9,8 +9,8 @@ #include "base/message_loop/message_loop.h" #include "base/observer_list.h" #include "ui/aura/aura_export.h" -#include "ui/base/events/event_handler.h" -#include "ui/base/events/event_target.h" +#include "ui/events/event_handler.h" +#include "ui/events/event_target.h" #include "ui/gfx/point.h" #if defined(USE_X11) @@ -60,9 +60,7 @@ class AURA_EXPORT Env : public ui::EventTarget { // Returns the native event dispatcher. The result should only be passed to // base::RunLoop(dispatcher), or used to dispatch an event by // |Dispatch(const NativeEvent&)| on it. It must never be stored. -#if !defined(OS_MACOSX) base::MessageLoop::Dispatcher* GetDispatcher(); -#endif // Invoked by RootWindow when its host is activated. void RootWindowActivated(RootWindow* root_window); diff --git a/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc b/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc index d377ef458a3..f17a32045ec 100644 --- a/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc +++ b/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc @@ -14,14 +14,14 @@ #include "ui/aura/test/event_generator.h" #include "ui/aura/test/test_window_delegate.h" #include "ui/aura/test/test_windows.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_utils.h" #include "ui/base/gestures/gesture_configuration.h" #include "ui/base/gestures/gesture_recognizer_impl.h" #include "ui/base/gestures/gesture_sequence.h" #include "ui/base/gestures/gesture_types.h" #include "ui/base/hit_test.h" #include "ui/base/ui_base_switches.h" +#include "ui/events/event.h" +#include "ui/events/event_utils.h" #include "ui/gfx/point.h" #include "ui/gfx/rect.h" @@ -2908,9 +2908,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTouchMoveConsumed) { tes.SendScrollEvent(root_window(), 130, 230, kTouchId, delegate.get()); EXPECT_FALSE(delegate->tap()); EXPECT_FALSE(delegate->tap_down()); - // TODO(rbyers): Really we should get the TapCancel here instead of below, - // but this is a symptom of a larger issue: crbug.com/146397. - EXPECT_FALSE(delegate->tap_cancel()); + EXPECT_TRUE(delegate->tap_cancel()); EXPECT_FALSE(delegate->begin()); EXPECT_FALSE(delegate->scroll_begin()); EXPECT_FALSE(delegate->scroll_update()); @@ -2924,7 +2922,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTouchMoveConsumed) { root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release); EXPECT_FALSE(delegate->tap()); EXPECT_FALSE(delegate->tap_down()); - EXPECT_TRUE(delegate->tap_cancel()); + EXPECT_FALSE(delegate->tap_cancel()); EXPECT_FALSE(delegate->begin()); EXPECT_TRUE(delegate->end()); EXPECT_FALSE(delegate->scroll_begin()); @@ -3059,9 +3057,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTouchMovePartialConsumed) { tes.SendScrollEvent(root_window(), 130, 230, kTouchId, delegate.get()); EXPECT_FALSE(delegate->tap()); EXPECT_FALSE(delegate->tap_down()); - // TODO(rbyers): Really we should get the TapCancel here instead of below, - // but this is a symptom of a larger issue: crbug.com/146397. - EXPECT_FALSE(delegate->tap_cancel()); + EXPECT_TRUE(delegate->tap_cancel()); EXPECT_FALSE(delegate->begin()); EXPECT_FALSE(delegate->scroll_begin()); EXPECT_FALSE(delegate->scroll_update()); @@ -3072,21 +3068,18 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTouchMovePartialConsumed) { tes.SendScrollEvent(root_window(), 159, 259, kTouchId, delegate.get()); EXPECT_FALSE(delegate->tap()); EXPECT_FALSE(delegate->tap_down()); - EXPECT_TRUE(delegate->tap_cancel()); + EXPECT_FALSE(delegate->tap_cancel()); EXPECT_FALSE(delegate->begin()); - EXPECT_TRUE(delegate->scroll_begin()); - EXPECT_TRUE(delegate->scroll_update()); + EXPECT_FALSE(delegate->scroll_begin()); + EXPECT_FALSE(delegate->scroll_update()); EXPECT_FALSE(delegate->scroll_end()); - // Consuming move events doesn't effect what the ultimate scroll position - // will be if scrolling is later allowed to happen. - EXPECT_EQ(58, delegate->scroll_x()); - EXPECT_EQ(58, delegate->scroll_y()); - EXPECT_EQ(gfx::Point(1, 1).ToString(), + // No scroll has occurred, because an early touch move was consumed. + EXPECT_EQ(0, delegate->scroll_x()); + EXPECT_EQ(0, delegate->scroll_y()); + EXPECT_EQ(gfx::Point(0, 0).ToString(), delegate->scroll_begin_position().ToString()); - // Start consuming touch-move events again. However, since gesture-scroll has - // already started, the touch-move events should still result in scroll-update - // gestures. + // Start consuming touch-move events again. delegate->set_consume_touch_move(true); // Move some more to generate a few more scroll updates. @@ -3096,10 +3089,10 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTouchMovePartialConsumed) { EXPECT_FALSE(delegate->tap_cancel()); EXPECT_FALSE(delegate->begin()); EXPECT_FALSE(delegate->scroll_begin()); - EXPECT_TRUE(delegate->scroll_update()); + EXPECT_FALSE(delegate->scroll_update()); EXPECT_FALSE(delegate->scroll_end()); - EXPECT_EQ(-49, delegate->scroll_x()); - EXPECT_EQ(-48, delegate->scroll_y()); + EXPECT_EQ(0, delegate->scroll_x()); + EXPECT_EQ(0, delegate->scroll_y()); tes.SendScrollEvent(root_window(), 140, 215, kTouchId, delegate.get()); EXPECT_FALSE(delegate->tap()); @@ -3107,12 +3100,12 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTouchMovePartialConsumed) { EXPECT_FALSE(delegate->tap_cancel()); EXPECT_FALSE(delegate->begin()); EXPECT_FALSE(delegate->scroll_begin()); - EXPECT_TRUE(delegate->scroll_update()); + EXPECT_FALSE(delegate->scroll_update()); EXPECT_FALSE(delegate->scroll_end()); - EXPECT_EQ(30, delegate->scroll_x()); - EXPECT_EQ(4, delegate->scroll_y()); + EXPECT_EQ(0, delegate->scroll_x()); + EXPECT_EQ(0, delegate->scroll_y()); - // Release the touch. This should end the scroll. + // Release the touch. delegate->Reset(); ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201), kTouchId, tes.LeapForward(50)); @@ -3125,8 +3118,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTouchMovePartialConsumed) { EXPECT_FALSE(delegate->scroll_begin()); EXPECT_FALSE(delegate->scroll_update()); EXPECT_FALSE(delegate->scroll_end()); - // Moves arrive without delays and hence have high velocity. - EXPECT_TRUE(delegate->fling()); + EXPECT_FALSE(delegate->fling()); } // Check that appropriate touch events generate double tap gesture events. @@ -3418,5 +3410,38 @@ TEST_F(GestureRecognizerTest, NoDriftInScroll) { delegate->Reset(); } +// Ensure that move events which are preventDefaulted will cause a tap +// cancel gesture event to be fired if the move would normally cause a +// scroll. See bug http://crbug.com/146397. +TEST_F(GestureRecognizerTest, GestureEventConsumedTouchMoveCanFireTapCancel) { + scoped_ptr<ConsumesTouchMovesDelegate> delegate( + new ConsumesTouchMovesDelegate()); + const int kTouchId = 5; + gfx::Rect bounds(100, 200, 123, 45); + scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate( + delegate.get(), -1234, bounds, root_window())); + TimedEvents tes; + + delegate->Reset(); + ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201), + kTouchId, tes.Now()); + + delegate->set_consume_touch_move(false); + root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press); + delegate->set_consume_touch_move(true); + delegate->Reset(); + // Move the touch-point enough so that it would normally be considered a + // scroll. But since the touch-moves will be consumed, the scroll should not + // start. + tes.SendScrollEvent(root_window(), 130, 230, kTouchId, delegate.get()); + EXPECT_FALSE(delegate->tap()); + EXPECT_FALSE(delegate->tap_down()); + EXPECT_TRUE(delegate->tap_cancel()); + EXPECT_FALSE(delegate->begin()); + EXPECT_FALSE(delegate->scroll_begin()); + EXPECT_FALSE(delegate->scroll_update()); + EXPECT_FALSE(delegate->scroll_end()); +} + } // namespace test } // namespace aura diff --git a/chromium/ui/aura/remote_root_window_host_win.cc b/chromium/ui/aura/remote_root_window_host_win.cc index f5dc26bff55..9d5cb8cf93a 100644 --- a/chromium/ui/aura/remote_root_window_host_win.cc +++ b/chromium/ui/aura/remote_root_window_host_win.cc @@ -15,8 +15,8 @@ #include "ui/aura/client/cursor_client.h" #include "ui/aura/root_window.h" #include "ui/base/cursor/cursor_loader_win.h" -#include "ui/base/events/event_utils.h" -#include "ui/base/keycodes/keyboard_code_conversion_win.h" +#include "ui/events/event_utils.h" +#include "ui/events/keycodes/keyboard_code_conversion_win.h" #include "ui/base/view_prop.h" #include "ui/gfx/insets.h" #include "ui/metro_viewer/metro_viewer_messages.h" @@ -108,33 +108,39 @@ void HandleSelectFolder(const base::string16& title, RemoteRootWindowHostWin* g_instance = NULL; RemoteRootWindowHostWin* RemoteRootWindowHostWin::Instance() { - return g_instance; + if (g_instance) + return g_instance; + return Create(gfx::Rect()); } RemoteRootWindowHostWin* RemoteRootWindowHostWin::Create( const gfx::Rect& bounds) { - g_instance = new RemoteRootWindowHostWin(bounds); + g_instance = g_instance ? g_instance : new RemoteRootWindowHostWin(bounds); return g_instance; } RemoteRootWindowHostWin::RemoteRootWindowHostWin(const gfx::Rect& bounds) - : delegate_(NULL), + : remote_window_(NULL), + delegate_(NULL), host_(NULL), ignore_mouse_moves_until_set_cursor_ack_(false) { prop_.reset(new ui::ViewProp(NULL, kRootWindowHostWinKey, this)); } RemoteRootWindowHostWin::~RemoteRootWindowHostWin() { + g_instance = NULL; } -void RemoteRootWindowHostWin::Connected(IPC::Sender* host) { +void RemoteRootWindowHostWin::Connected(IPC::Sender* host, HWND remote_window) { CHECK(host_ == NULL); host_ = host; + remote_window_ = remote_window; } void RemoteRootWindowHostWin::Disconnected() { CHECK(host_ != NULL); host_ = NULL; + remote_window_ = NULL; } bool RemoteRootWindowHostWin::OnMessageReceived(const IPC::Message& message) { @@ -161,8 +167,6 @@ bool RemoteRootWindowHostWin::OnMessageReceived(const IPC::Message& message) { OnMultiFileOpenDone) IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SelectFolderDone, OnSelectFolderDone) - IPC_MESSAGE_HANDLER(MetroViewerHostMsg_WindowActivated, - OnWindowActivated) IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SetCursorPosAck, OnSetCursorPosAck) IPC_MESSAGE_HANDLER(MetroViewerHostMsg_WindowSizeChanged, @@ -172,6 +176,14 @@ bool RemoteRootWindowHostWin::OnMessageReceived(const IPC::Message& message) { return handled; } +void RemoteRootWindowHostWin::HandleOpenURLOnDesktop( + const base::FilePath& shortcut, + const base::string16& url) { + if (!host_) + return; + host_->Send(new MetroViewerHostMsg_OpenURLOnDesktop(shortcut, url)); +} + void RemoteRootWindowHostWin::HandleOpenFile( const base::string16& title, const base::FilePath& default_path, @@ -271,10 +283,9 @@ RootWindow* RemoteRootWindowHostWin::GetRootWindow() { } gfx::AcceleratedWidget RemoteRootWindowHostWin::GetAcceleratedWidget() { - // TODO(cpu): This is bad. Chrome's compositor needs a valid window - // initially and then later on we swap it. Since the compositor never - // uses this initial window we tell ourselves this hack is ok to get - // thing off the ground. + if (remote_window_) + return remote_window_; + // Getting here should only happen for ash_unittests.exe and related code. return ::GetDesktopWindow(); } @@ -339,13 +350,6 @@ bool RemoteRootWindowHostWin::ConfineCursorToRootWindow() { return true; } -bool RemoteRootWindowHostWin::CopyAreaToSkCanvas(const gfx::Rect& source_bounds, - const gfx::Point& dest_offset, - SkCanvas* canvas) { - NOTIMPLEMENTED(); - return false; -} - void RemoteRootWindowHostWin::UnConfineCursor() { } @@ -538,10 +542,6 @@ void RemoteRootWindowHostWin::OnSelectFolderDone( failure_callback_.Reset(); } -void RemoteRootWindowHostWin::OnWindowActivated(bool active) { - active ? GetRootWindow()->Focus() : GetRootWindow()->Blur(); -} - void RemoteRootWindowHostWin::OnSetCursorPosAck() { DCHECK(ignore_mouse_moves_until_set_cursor_ack_); ignore_mouse_moves_until_set_cursor_ack_ = false; diff --git a/chromium/ui/aura/remote_root_window_host_win.h b/chromium/ui/aura/remote_root_window_host_win.h index 132f0f236f0..e92a5add625 100644 --- a/chromium/ui/aura/remote_root_window_host_win.h +++ b/chromium/ui/aura/remote_root_window_host_win.h @@ -11,8 +11,8 @@ #include "base/compiler_specific.h" #include "base/strings/string16.h" #include "ui/aura/root_window_host.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_constants.h" +#include "ui/events/event.h" +#include "ui/events/event_constants.h" #include "ui/gfx/native_widget_types.h" namespace base { @@ -86,18 +86,24 @@ AURA_EXPORT void HandleSelectFolder(const base::string16& title, // frontend process, which forwards input events to this class. class AURA_EXPORT RemoteRootWindowHostWin : public RootWindowHost { public: + // Returns the only RemoteRootWindowHostWin, if this is the first time + // this function is called, it will call Create() wiht empty bounds. static RemoteRootWindowHostWin* Instance(); static RemoteRootWindowHostWin* Create(const gfx::Rect& bounds); // Called when the remote process has established its IPC connection. - // The |host| can be used when we need to send a message to it. - void Connected(IPC::Sender* host); + // The |host| can be used when we need to send a message to it and + // |remote_window| is the actual window owned by the viewer process. + void Connected(IPC::Sender* host, HWND remote_window); // Called when the remote process has closed its IPC connection. void Disconnected(); // Called when we have a message from the remote process. bool OnMessageReceived(const IPC::Message& message); + void HandleOpenURLOnDesktop(const base::FilePath& shortcut, + const base::string16& url); + void HandleOpenFile(const base::string16& title, const base::FilePath& default_path, const base::string16& filter, @@ -159,7 +165,6 @@ class AURA_EXPORT RemoteRootWindowHostWin : public RootWindowHost { void OnMultiFileOpenDone(bool success, const std::vector<base::FilePath>& files); void OnSelectFolderDone(bool success, const base::FilePath& folder); - void OnWindowActivated(bool active); void OnSetCursorPosAck(); void OnWindowSizeChanged(uint32 width, uint32 height); @@ -184,9 +189,6 @@ class AURA_EXPORT RemoteRootWindowHostWin : public RootWindowHost { virtual void OnCursorVisibilityChanged(bool show) OVERRIDE; virtual void MoveCursorTo(const gfx::Point& location) OVERRIDE; virtual void SetFocusWhenShown(bool focus_when_shown) OVERRIDE; - virtual bool CopyAreaToSkCanvas(const gfx::Rect& source_bounds, - const gfx::Point& dest_offset, - SkCanvas* canvas) OVERRIDE; virtual void PostNativeEvent(const base::NativeEvent& native_event) OVERRIDE; virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE; virtual void PrepareForShutdown() OVERRIDE; @@ -203,6 +205,7 @@ class AURA_EXPORT RemoteRootWindowHostWin : public RootWindowHost { uint32 flags, bool is_character); + HWND remote_window_; RootWindowHostDelegate* delegate_; IPC::Sender* host_; scoped_ptr<ui::ViewProp> prop_; diff --git a/chromium/ui/aura/root_window.cc b/chromium/ui/aura/root_window.cc index 43366f001aa..303ec90f18e 100644 --- a/chromium/ui/aura/root_window.cc +++ b/chromium/ui/aura/root_window.cc @@ -6,7 +6,6 @@ #include <vector> -#include "base/auto_reset.h" #include "base/bind.h" #include "base/command_line.h" #include "base/debug/trace_event.h" @@ -25,7 +24,6 @@ #include "ui/aura/window.h" #include "ui/aura/window_delegate.h" #include "ui/aura/window_tracker.h" -#include "ui/base/events/event.h" #include "ui/base/gestures/gesture_recognizer.h" #include "ui/base/gestures/gesture_types.h" #include "ui/base/hit_test.h" @@ -34,6 +32,7 @@ #include "ui/compositor/dip_util.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animator.h" +#include "ui/events/event.h" #include "ui/gfx/display.h" #include "ui/gfx/point3_f.h" #include "ui/gfx/point_conversions.h" @@ -149,7 +148,6 @@ RootWindow::RootWindow(const CreateParams& params) last_cursor_(ui::kCursorNull), mouse_pressed_handler_(NULL), mouse_moved_handler_(NULL), - mouse_event_dispatch_target_(NULL), event_dispatch_target_(NULL), gesture_recognizer_(ui::GestureRecognizer::Create(this)), synthesize_mouse_move_(false), @@ -171,6 +169,8 @@ RootWindow::RootWindow(const CreateParams& params) } RootWindow::~RootWindow() { + TRACE_EVENT0("shutdown", "RootWindow::Destructor"); + compositor_->RemoveObserver(this); // Make sure to destroy the compositor before terminating so that state is // cleared and we don't hit asserts. @@ -216,6 +216,8 @@ void RootWindow::PrepareForShutdown() { } void RootWindow::RepostEvent(const ui::LocatedEvent& event) { + DCHECK(event.type() == ui::ET_MOUSE_PRESSED || + event.type() == ui::ET_GESTURE_TAP_DOWN); // We allow for only one outstanding repostable event. This is used // in exiting context menus. A dropped repost request is allowed. if (event.type() == ui::ET_MOUSE_PRESSED) { @@ -231,7 +233,8 @@ void RootWindow::RepostEvent(const ui::LocatedEvent& event) { } else { DCHECK(event.type() == ui::ET_GESTURE_TAP_DOWN); held_repostable_event_.reset(); - // TODO(sschmitz): add similar code for gesture events. + // TODO(rbyers): Reposing of gestures is tricky to get + // right, so it's not yet supported. crbug.com/170987. } } @@ -276,6 +279,13 @@ void RootWindow::SetCursor(gfx::NativeCursor cursor) { } void RootWindow::OnCursorVisibilityChanged(bool show) { + // Clear any existing mouse hover effects when the cursor becomes invisible. + // Note we do not need to dispatch a mouse enter when the cursor becomes + // visible because that can only happen in response to a mouse event, which + // will trigger its own mouse enter. + if (!show) + DispatchMouseExitAtPoint(GetLastMouseLocationInRoot()); + host_->OnCursorVisibilityChanged(show); } @@ -378,13 +388,13 @@ void RootWindow::DispatchMouseExitToHidingWindow(Window* window) { // |window| is the capture window. gfx::Point last_mouse_location = GetLastMouseLocationInRoot(); if (window->Contains(mouse_moved_handler_) && - window->ContainsPointInRoot(last_mouse_location)) { - ui::MouseEvent event(ui::ET_MOUSE_EXITED, - last_mouse_location, - last_mouse_location, - ui::EF_NONE); - DispatchMouseEnterOrExit(event, ui::ET_MOUSE_EXITED); - } + window->ContainsPointInRoot(last_mouse_location)) + DispatchMouseExitAtPoint(last_mouse_location); +} + +void RootWindow::DispatchMouseExitAtPoint(const gfx::Point& point) { + ui::MouseEvent event(ui::ET_MOUSE_EXITED, point, point, ui::EF_NONE); + DispatchMouseEnterOrExit(event, ui::ET_MOUSE_EXITED); } void RootWindow::OnWindowVisibilityChanged(Window* window, bool is_visible) { @@ -422,9 +432,7 @@ void RootWindow::RemoveRootWindowObserver(RootWindowObserver* observer) { } void RootWindow::PostNativeEvent(const base::NativeEvent& native_event) { -#if !defined(OS_MACOSX) host_->PostNativeEvent(native_event); -#endif } void RootWindow::ConvertPointToNativeScreen(gfx::Point* point) const { @@ -441,13 +449,13 @@ void RootWindow::ConvertPointFromNativeScreen(gfx::Point* point) const { void RootWindow::ConvertPointToHost(gfx::Point* point) const { gfx::Point3F point_3f(*point); - GetRootTransform().TransformPoint(point_3f); + GetRootTransform().TransformPoint(&point_3f); *point = gfx::ToFlooredPoint(point_3f.AsPointF()); } void RootWindow::ConvertPointFromHost(gfx::Point* point) const { gfx::Point3F point_3f(*point); - GetInverseRootTransform().TransformPoint(point_3f); + GetInverseRootTransform().TransformPoint(&point_3f); *point = gfx::ToFlooredPoint(point_3f.AsPointF()); } @@ -499,15 +507,6 @@ void RootWindow::SetFocusWhenShown(bool focused) { host_->SetFocusWhenShown(focused); } -bool RootWindow::CopyAreaToSkCanvas(const gfx::Rect& source_bounds, - const gfx::Point& dest_offset, - SkCanvas* canvas) { - DCHECK(canvas); - DCHECK(bounds().Contains(source_bounds)); - gfx::Rect source_pixels = ui::ConvertRectToPixel(layer(), source_bounds); - return host_->CopyAreaToSkCanvas(source_pixels, dest_offset, canvas); -} - gfx::Point RootWindow::GetLastMouseLocationInRoot() const { gfx::Point location = Env::GetInstance()->last_mouse_location(); client::ScreenPositionClient* client = client::GetScreenPositionClient(this); @@ -654,6 +653,14 @@ bool RootWindow::CanReceiveEvents() const { void RootWindow::UpdateCapture(Window* old_capture, Window* new_capture) { + if (!new_capture && old_capture && old_capture->GetRootWindow() != this) { + // If we no longer contain the window that had capture make sure we clean + // state in the GestureRecognizer. Since we don't contain the window we'll + // never get notification of its destruction and clean up state. + // We do this early on as OnCaptureLost() may delete |old_capture|. + gesture_recognizer_->CleanupStateForConsumer(old_capture); + } + if (old_capture && old_capture->GetRootWindow() == this && old_capture->delegate()) { // Send a capture changed event with bogus location data. @@ -674,9 +681,8 @@ void RootWindow::UpdateCapture(Window* old_capture, } if (new_capture) { - // Make all subsequent mouse events and touch go to the capture window. We - // shouldn't need to send an event here as OnCaptureLost should take care of - // that. + // Make all subsequent mouse events go to the capture window. We shouldn't + // need to send an event here as OnCaptureLost() should take care of that. if (mouse_moved_handler_ || Env::GetInstance()->is_mouse_button_down()) mouse_moved_handler_ = new_capture; } else { @@ -698,12 +704,6 @@ bool RootWindow::QueryMouseLocationForTest(gfx::Point* point) const { return host_->QueryMouseLocation(point); } -void RootWindow::ClearMouseHandlers() { - mouse_pressed_handler_ = NULL; - mouse_moved_handler_ = NULL; - mouse_event_dispatch_target_ = NULL; -} - //////////////////////////////////////////////////////////////////////////////// // RootWindow, private: @@ -724,22 +724,6 @@ void RootWindow::MoveCursorToInternal(const gfx::Point& root_location, synthesize_mouse_move_ = false; } -void RootWindow::HandleMouseMoved(const ui::MouseEvent& event, Window* target) { - if (target == mouse_moved_handler_) - return; - - DispatchMouseEnterOrExit(event, ui::ET_MOUSE_EXITED); - - if (mouse_event_dispatch_target_ != target) { - mouse_moved_handler_ = NULL; - return; - } - - mouse_moved_handler_ = target; - - DispatchMouseEnterOrExit(event, ui::ET_MOUSE_ENTERED); -} - void RootWindow::DispatchMouseEnterOrExit(const ui::MouseEvent& event, ui::EventType type) { if (!mouse_moved_handler_ || !mouse_moved_handler_->delegate()) @@ -825,15 +809,13 @@ void RootWindow::OnWindowHidden(Window* invisible, WindowHiddenReason reason) { mouse_pressed_handler_ = NULL; if (invisible->Contains(mouse_moved_handler_)) mouse_moved_handler_ = NULL; - if (invisible->Contains(mouse_event_dispatch_target_)) - mouse_event_dispatch_target_ = NULL; CleanupGestureRecognizerState(invisible); } void RootWindow::CleanupGestureRecognizerState(Window* window) { gesture_recognizer_->CleanupStateForConsumer(window); - Windows windows = window->children(); + const Windows& windows = window->children(); for (Windows::const_iterator iter = windows.begin(); iter != windows.end(); ++iter) { @@ -973,7 +955,8 @@ void RootWindow::OnHostLostWindowCapture() { } void RootWindow::OnHostLostMouseGrab() { - ClearMouseHandlers(); + mouse_pressed_handler_ = NULL; + mouse_moved_handler_ = NULL; } void RootWindow::OnHostPaint(const gfx::Rect& damage_rect) { @@ -1038,21 +1021,46 @@ bool RootWindow::DispatchMouseEventToTarget(ui::MouseEvent* event, ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON; - base::AutoReset<Window*> reset(&mouse_event_dispatch_target_, target); + // WARNING: because of nested message loops |this| may be deleted after + // dispatching any event. Do not use AutoReset or the like here. + WindowTracker destroyed_tracker; + destroyed_tracker.Add(this); SetLastMouseLocation(this, event->location()); synthesize_mouse_move_ = false; switch (event->type()) { case ui::ET_MOUSE_EXITED: if (!target) { DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_EXITED); + if (!destroyed_tracker.Contains(this)) + return false; mouse_moved_handler_ = NULL; } break; case ui::ET_MOUSE_MOVED: - mouse_event_dispatch_target_ = target; - HandleMouseMoved(*event, target); - if (mouse_event_dispatch_target_ != target) - return false; + // Send an exit to the current |mouse_moved_handler_| and an enter to + // |target|. Take care that both us and |target| aren't destroyed during + // dispatch. + if (target != mouse_moved_handler_) { + aura::Window* old_mouse_moved_handler = mouse_moved_handler_; + if (target) + destroyed_tracker.Add(target); + DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_EXITED); + if (!destroyed_tracker.Contains(this)) + return false; + // If the |mouse_moved_handler_| changes out from under us, assume a + // nested message loop ran and we don't need to do anything. + if (mouse_moved_handler_ != old_mouse_moved_handler) + return false; + if (destroyed_tracker.Contains(target)) { + destroyed_tracker.Remove(target); + mouse_moved_handler_ = target; + DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_ENTERED); + if (!destroyed_tracker.Contains(this)) + return false; + } else { + mouse_moved_handler_ = NULL; + } + } break; case ui::ET_MOUSE_PRESSED: // Don't set the mouse pressed handler for non client mouse down events. @@ -1072,14 +1080,19 @@ bool RootWindow::DispatchMouseEventToTarget(ui::MouseEvent* event, default: break; } + bool result; if (target) { event->ConvertLocationToTarget(static_cast<Window*>(this), target); if (IsNonClientLocation(target, event->location())) event->set_flags(event->flags() | ui::EF_IS_NON_CLIENT); ProcessEvent(target, event); - return event->handled(); + if (!destroyed_tracker.Contains(this)) + return false; + result = event->handled(); + } else { + result = false; } - return false; + return result; } bool RootWindow::DispatchTouchEventImpl(ui::TouchEvent* event) { @@ -1153,11 +1166,11 @@ void RootWindow::DispatchHeldEvents() { if (held_repostable_event_->type() == ui::ET_MOUSE_PRESSED) { ui::MouseEvent mouse_event( static_cast<const ui::MouseEvent&>(*held_repostable_event_.get())); - held_repostable_event_.reset(); // must be reset before dispatch + held_repostable_event_.reset(); // must be reset before dispatch DispatchMouseEventRepost(&mouse_event); } else { - DCHECK(held_repostable_event_->type() == ui::ET_GESTURE_TAP_DOWN); - // TODO(sschmitz): add similar code for gesture events + // TODO(rbyers): GESTURE_TAP_DOWN not yet supported: crbug.com/170987. + NOTREACHED(); } held_repostable_event_.reset(); } diff --git a/chromium/ui/aura/root_window.h b/chromium/ui/aura/root_window.h index e8a6b260f85..10ce2d507bf 100644 --- a/chromium/ui/aura/root_window.h +++ b/chromium/ui/aura/root_window.h @@ -18,19 +18,17 @@ #include "ui/aura/root_window_host_delegate.h" #include "ui/aura/window.h" #include "ui/base/cursor/cursor.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/events/event_dispatcher.h" #include "ui/base/gestures/gesture_recognizer.h" #include "ui/base/gestures/gesture_types.h" #include "ui/compositor/compositor.h" #include "ui/compositor/compositor_observer.h" #include "ui/compositor/layer_animation_observer.h" +#include "ui/events/event_constants.h" +#include "ui/events/event_dispatcher.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/point.h" #include "ui/gfx/transform.h" -class SkCanvas; - namespace gfx { class Size; class Transform; @@ -86,6 +84,7 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, ui::Compositor* compositor() { return compositor_.get(); } gfx::NativeCursor last_cursor() const { return last_cursor_; } Window* mouse_pressed_handler() { return mouse_pressed_handler_; } + Window* mouse_moved_handler() { return mouse_moved_handler_; } // Initializes the root window. void Init(); @@ -100,6 +99,8 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, void PrepareForShutdown(); // Repost event for re-processing. Used when exiting context menus. + // We only support the ET_MOUSE_PRESSED and ET_GESTURE_TAP_DOWN event + // types (although the latter is currently a no-op). void RepostEvent(const ui::LocatedEvent& event); RootWindowHostDelegate* AsRootWindowHostDelegate(); @@ -162,6 +163,9 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, // Dispatches OnMouseExited to the |window| which is hiding if nessessary. void DispatchMouseExitToHidingWindow(Window* window); + // Dispatches a ui::ET_MOUSE_EXITED event at |point|. + void DispatchMouseExitAtPoint(const gfx::Point& point); + // Invoked when |window|'s visibility has changed. void OnWindowVisibilityChanged(Window* window, bool is_visible); @@ -239,12 +243,6 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, // Sets if the window should be focused when shown. void SetFocusWhenShown(bool focus_when_shown); - // Copies |source_bounds| from the root window (as displayed on the host - // machine) to |canvas| at offset |dest_offset|. - bool CopyAreaToSkCanvas(const gfx::Rect& source_bounds, - const gfx::Point& dest_offset, - SkCanvas* canvas); - // Gets the last location seen in a mouse event in this root window's // coordinates. This may return a point outside the root window's bounds. gfx::Point GetLastMouseLocationInRoot() const; @@ -286,10 +284,6 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, // Exposes RootWindowHost::QueryMouseLocation() for test purposes. bool QueryMouseLocationForTest(gfx::Point* point) const; - // Clears internal mouse state (such as mouse ups should be sent to the same - // window that ate mouse downs). - void ClearMouseHandlers(); - void SetRootWindowTransformer(scoped_ptr<RootWindowTransformer> transformer); gfx::Transform GetRootTransform() const; @@ -319,10 +313,6 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, void MoveCursorToInternal(const gfx::Point& root_location, const gfx::Point& host_location); - // Called whenever the mouse moves, tracks the current |mouse_moved_handler_|, - // sending exited and entered events as its value changes. - void HandleMouseMoved(const ui::MouseEvent& event, Window* target); - // Dispatches the specified event type (intended for enter/exit) to the // |mouse_moved_handler_|. void DispatchMouseEnterOrExit(const ui::MouseEvent& event, @@ -426,7 +416,6 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, Window* mouse_pressed_handler_; Window* mouse_moved_handler_; - Window* mouse_event_dispatch_target_; Window* event_dispatch_target_; // The gesture_recognizer_ for this. diff --git a/chromium/ui/aura/root_window_host.h b/chromium/ui/aura/root_window_host.h index 09e48fad817..0528ae179a1 100644 --- a/chromium/ui/aura/root_window_host.h +++ b/chromium/ui/aura/root_window_host.h @@ -12,8 +12,6 @@ #include "ui/base/cursor/cursor.h" #include "ui/gfx/native_widget_types.h" -class SkCanvas; - namespace gfx { class Insets; class Point; @@ -99,17 +97,8 @@ class AURA_EXPORT RootWindowHost { // Sets if the window should be focused when shown. virtual void SetFocusWhenShown(bool focus_when_shown) = 0; - // Copies |source_bounds| from the root window (as displayed on the host - // machine) to |canvas| at offset |dest_offset|. The bounds need to be in - // physical pixels. - virtual bool CopyAreaToSkCanvas(const gfx::Rect& source_bounds, - const gfx::Point& dest_offset, - SkCanvas* canvas) = 0; - // Posts |native_event| to the platform's event queue. -#if !defined(OS_MACOSX) virtual void PostNativeEvent(const base::NativeEvent& native_event) = 0; -#endif // Called when the device scale factor of the root window has chagned. virtual void OnDeviceScaleFactorChanged(float device_scale_factor) = 0; diff --git a/chromium/ui/aura/root_window_host_mac.h b/chromium/ui/aura/root_window_host_mac.h deleted file mode 100644 index e7c26c35482..00000000000 --- a/chromium/ui/aura/root_window_host_mac.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef UI_AURA_ROOT_WINDOW_HOST_MAC_H_ -#define UI_AURA_ROOT_WINDOW_HOST_MAC_H_ - -#include "base/basictypes.h" -#include "base/event_types.h" - -namespace aura { - -// An interface establishing event dispatch from the Mac native window and the -// Aura host. -class RootWindowHostMacDelegate { - public: - RootWindowHostMacDelegate(); - virtual ~RootWindowHostMacDelegate(); - - // Route events from platform code to the RootWindowHost. - virtual void SendEvent(const base::NativeEvent& native_event) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(RootWindowHostMacDelegate); -}; - -} // namespace aura - -#endif // UI_AURA_ROOT_WINDOW_HOST_MAC_H_ diff --git a/chromium/ui/aura/root_window_host_mac.mm b/chromium/ui/aura/root_window_host_mac.mm deleted file mode 100644 index 28943a958f9..00000000000 --- a/chromium/ui/aura/root_window_host_mac.mm +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright (c) 2012 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 "ui/aura/root_window_host_mac.h" - -#import <Cocoa/Cocoa.h> - -#include "base/compiler_specific.h" -#include "base/mac/bundle_locations.h" -#include "base/mac/scoped_nsobject.h" -#include "ui/aura/event.h" -#include "ui/aura/root_window.h" -#include "ui/aura/root_window_host.h" -#include "ui/aura/root_window_mac.h" -#include "ui/aura/root_window_view_mac.h" -#include "ui/base/events/event_utils.h" -#include "ui/gfx/point.h" - -namespace aura { - -// The Mac-specific implementation of the RootWindowHost interface. This class -// acts at an intermediary between the Aura shell and an NSWindow. The -// association between the Aura compositor and the native window's view is -// established with this class as is the association between the native window's -// event dispatch and the Aura event processing. -class RootWindowHostMac : public RootWindowHost, - public RootWindowHostMacDelegate { - public: - explicit RootWindowHostMac(const gfx::Rect& bounds); - virtual ~RootWindowHostMac(); - - // RootWindowHost: - virtual void SetRootWindow(RootWindow* root_window) OVERRIDE; - virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE; - virtual void Show() OVERRIDE; - virtual void ToggleFullScreen() OVERRIDE; - virtual gfx::Size GetSize() const OVERRIDE; - virtual void SetSize(const gfx::Size& size) OVERRIDE; - virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE; - virtual void SetCapture() OVERRIDE; - virtual void ReleaseCapture() OVERRIDE; - virtual void SetCursor(gfx::NativeCursor cursor) OVERRIDE; - virtual void ShowCursor(bool show) OVERRIDE; - virtual bool QueryMouseLocation(gfx::Point* location_return) OVERRIDE; - virtual void MoveCursorTo(const gfx::Point& location) OVERRIDE; - virtual bool ConfineCursorToRootWindow() OVERRIDE; - virtual void UnConfineCursor() OVERRIDE; - virtual bool CopyAreaToSkCanvas(const gfx::Rect& source_bounds, - const gfx::Point& dest_offset, - SkCanvas* canvas) OVERRIDE; - // RootWindowHostMacDelegate: - virtual void SendEvent(const base::NativeEvent& native_event) OVERRIDE; - - // Set the initial location of the root window. The origin of |bounds| is - // top-left. This gets converted to bottom-left to match Mac coordinates on - // the main screen. - void SetLocation(const gfx::Rect& bounds); - - private: - // Weak reference. - RootWindow* root_window_; - - // The bounds of the Aura desktop. Relative to Aura's coordinate system. - // This is currently used only for size information, not location. - gfx::Rect bounds_; - - // An NSWindowController for the root window. Controls the actual Cocoa - // window on Mac. - base::scoped_nsobject<NSWindowController> controller_; - - DISALLOW_COPY_AND_ASSIGN(RootWindowHostMac); -}; - -RootWindowHostMacDelegate::RootWindowHostMacDelegate() { -} - -RootWindowHostMacDelegate::~RootWindowHostMacDelegate() { -} - -RootWindowHostMac::RootWindowHostMac(const gfx::Rect& bounds) - : root_window_(NULL), bounds_(bounds) { - NSString* nibpath = [base::mac::FrameworkBundle() - pathForResource:@"RootWindow" - ofType:@"nib"]; - NSWindowController* controller = [NSWindowController alloc]; - controller_.reset([controller initWithWindowNibPath:nibpath - owner:controller]); - SetSize(bounds.size()); - SetLocation(bounds); -} - -RootWindowHostMac::~RootWindowHostMac() { - RootWindowView* view = [[controller_ window] contentView]; - [view setCompositor:NULL]; - [controller_ close]; -} - -// static -RootWindowHost* RootWindowHost::Create(const gfx::Rect& bounds) { - return new RootWindowHostMac(bounds); -} - -// static -gfx::Size RootWindowHost::GetNativeScreenSize() { - NSRect screen = [[NSScreen mainScreen] visibleFrame]; - return gfx::Size(NSSizeToCGSize(screen.size)); -} - -void RootWindowHostMac::SetRootWindow(RootWindow* root_window) { - root_window_ = root_window; - - RootWindowView* view = [[controller_ window] contentView]; - DCHECK([view respondsToSelector:@selector(setCompositor:)]); - [view setCompositor:root_window->compositor()]; - - RootWindowMac* window = static_cast<RootWindowMac*>([controller_ window]); - DCHECK([window respondsToSelector:@selector(setHostDelegate:)]); - [window setHostDelegate:this]; -} - -gfx::AcceleratedWidget RootWindowHostMac::GetAcceleratedWidget() { - return [[controller_ window] contentView]; -} - -void RootWindowHostMac::Show() { - [controller_ showWindow:controller_]; -} - -void RootWindowHostMac::ToggleFullScreen() { -} - -gfx::Size RootWindowHostMac::GetSize() const { - NSSize size = [[[controller_ window] contentView] bounds].size; - return gfx::Size(NSSizeToCGSize(size)); -} - -void RootWindowHostMac::SetSize(const gfx::Size& size) { - NSSize nssize = NSSizeFromCGSize(size.ToCGSize()); - [[controller_ window] setContentSize:nssize]; - [[controller_ window] setContentMaxSize:nssize]; - [[controller_ window] setContentMinSize:nssize]; -} - -gfx::Point RootWindowHostMac::GetLocationOnNativeScreen() const { - return gfx::Point(); -} - -void RootWindowHostMac::SetCapture() { -} - -void RootWindowHostMac::ReleaseCapture() { -} - -void RootWindowHostMac::SetCursor(gfx::NativeCursor cursor) { -} - -void RootWindowHostMac::ShowCursor(bool show) { -} - -bool RootWindowHostMac::QueryMouseLocation(gfx::Point* location_return) { - *location_return = gfx::Point(); - return true; -} - -void RootWindowHostMac::MoveCursorTo(const gfx::Point& location) { -} - -bool RootWindowHostMac::ConfineCursorToRootWindow() { - return false; -} - -void RootWindowHostMac::UnConfineCursor() { -} - -void RootWindowHostMac::SendEvent(const base::NativeEvent& native_event) { - ui::EventType type = ui::EventTypeFromNative(native_event); - switch (type) { - case ui::ET_MOUSE_PRESSED: - case ui::ET_MOUSE_DRAGGED: - case ui::ET_MOUSE_RELEASED: - case ui::ET_MOUSE_MOVED: - case ui::ET_MOUSE_ENTERED: - case ui::ET_MOUSE_EXITED: { - MouseEvent mouse_event(native_event); - root_window_->DispatchMouseEvent(&mouse_event); - break; - } - case ui::ET_KEY_PRESSED: - case ui::ET_KEY_RELEASED: { - KeyEvent key_event(native_event, false); - root_window_->DispatchKeyEvent(&key_event); - break; - } - case ui::ET_MOUSEWHEEL: - case ui::ET_TOUCH_RELEASED: - case ui::ET_TOUCH_PRESSED: - case ui::ET_TOUCH_MOVED: - case ui::ET_TOUCH_STATIONARY: - case ui::ET_TOUCH_CANCELLED: - case ui::ET_DROP_TARGET_EVENT: - case ui::ET_FOCUS_CHANGE: - case ui::ET_SCROLL: - case ui::ET_UNKNOWN: - default: - break; - } -} - -void RootWindowHostMac::SetLocation(const gfx::Rect& bounds) { - NSRect screen = [[NSScreen mainScreen] visibleFrame]; - NSPoint origin = NSMakePoint(screen.origin.x + bounds.x(), - screen.origin.y + screen.size.height - - bounds.y() - bounds.height()); - [[controller_ window] setFrameOrigin:origin]; -} - -} // namespace aura diff --git a/chromium/ui/aura/root_window_host_ozone.cc b/chromium/ui/aura/root_window_host_ozone.cc index 28c8d0c4807..3af82898e79 100644 --- a/chromium/ui/aura/root_window_host_ozone.cc +++ b/chromium/ui/aura/root_window_host_ozone.cc @@ -5,7 +5,7 @@ #include "ui/aura/root_window_host_ozone.h" #include "ui/aura/root_window.h" -#include "ui/base/ozone/surface_factory_ozone.h" +#include "ui/gfx/ozone/surface_factory_ozone.h" namespace aura { @@ -15,8 +15,8 @@ RootWindowHostOzone::RootWindowHostOzone(const gfx::Rect& bounds) bounds_(bounds), factory_(new ui::EventFactoryOzone()) { factory_->CreateStartupEventConverters(); - ui::SurfaceFactoryOzone* surface_factory = - ui::SurfaceFactoryOzone::GetInstance(); + gfx::SurfaceFactoryOzone* surface_factory = + gfx::SurfaceFactoryOzone::GetInstance(); widget_ = surface_factory->GetAcceleratedWidget(); surface_factory->AttemptToResizeAcceleratedWidget(widget_, bounds_); @@ -106,13 +106,6 @@ void RootWindowHostOzone::SetFocusWhenShown(bool focus_when_shown) { NOTIMPLEMENTED(); } -bool RootWindowHostOzone::CopyAreaToSkCanvas(const gfx::Rect& source_bounds, - const gfx::Point& dest_offset, - SkCanvas* canvas) { - NOTIMPLEMENTED(); - return false; -} - void RootWindowHostOzone::PostNativeEvent( const base::NativeEvent& native_event) { NOTIMPLEMENTED(); diff --git a/chromium/ui/aura/root_window_host_ozone.h b/chromium/ui/aura/root_window_host_ozone.h index 6acd1a2c0ce..8be9e484fc3 100644 --- a/chromium/ui/aura/root_window_host_ozone.h +++ b/chromium/ui/aura/root_window_host_ozone.h @@ -10,7 +10,7 @@ #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "ui/aura/root_window_host.h" -#include "ui/base/ozone/event_factory_ozone.h" +#include "ui/events/ozone/event_factory_ozone.h" #include "ui/gfx/rect.h" namespace aura { @@ -46,9 +46,6 @@ class RootWindowHostOzone : public RootWindowHost, virtual void OnCursorVisibilityChanged(bool show) OVERRIDE; virtual void MoveCursorTo(const gfx::Point& location) OVERRIDE; virtual void SetFocusWhenShown(bool focus_when_shown) OVERRIDE; - virtual bool CopyAreaToSkCanvas(const gfx::Rect& source_bounds, - const gfx::Point& dest_offset, - SkCanvas* canvas) OVERRIDE; virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE; virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE; virtual void PrepareForShutdown() OVERRIDE; diff --git a/chromium/ui/aura/root_window_host_win.cc b/chromium/ui/aura/root_window_host_win.cc index 5c67b776d07..e5658f76447 100644 --- a/chromium/ui/aura/root_window_host_win.cc +++ b/chromium/ui/aura/root_window_host_win.cc @@ -13,7 +13,7 @@ #include "ui/aura/client/cursor_client.h" #include "ui/aura/root_window.h" #include "ui/base/cursor/cursor_loader_win.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" #include "ui/base/view_prop.h" #include "ui/gfx/display.h" #include "ui/gfx/insets.h" @@ -210,13 +210,6 @@ bool RootWindowHostWin::ConfineCursorToRootWindow() { return ClipCursor(&window_rect) != 0; } -bool RootWindowHostWin::CopyAreaToSkCanvas(const gfx::Rect& source_bounds, - const gfx::Point& dest_offset, - SkCanvas* canvas) { - NOTIMPLEMENTED(); - return false; -} - void RootWindowHostWin::UnConfineCursor() { ClipCursor(NULL); } diff --git a/chromium/ui/aura/root_window_host_win.h b/chromium/ui/aura/root_window_host_win.h index 491ab903445..42c8ada89ca 100644 --- a/chromium/ui/aura/root_window_host_win.h +++ b/chromium/ui/aura/root_window_host_win.h @@ -8,11 +8,11 @@ #include "base/compiler_specific.h" #include "ui/aura/root_window_host.h" #include "ui/base/ui_export.h" -#include "ui/base/win/window_impl.h" +#include "ui/gfx/win/window_impl.h" namespace aura { -class RootWindowHostWin : public RootWindowHost, public ui::WindowImpl { +class RootWindowHostWin : public RootWindowHost, public gfx::WindowImpl { public: RootWindowHostWin(const gfx::Rect& bounds); virtual ~RootWindowHostWin(); @@ -37,9 +37,6 @@ class RootWindowHostWin : public RootWindowHost, public ui::WindowImpl { virtual void OnCursorVisibilityChanged(bool show) OVERRIDE; virtual void MoveCursorTo(const gfx::Point& location) OVERRIDE; virtual void SetFocusWhenShown(bool focus_when_shown) OVERRIDE; - virtual bool CopyAreaToSkCanvas(const gfx::Rect& source_bounds, - const gfx::Point& dest_offset, - SkCanvas* canvas) OVERRIDE; virtual void PostNativeEvent(const base::NativeEvent& native_event) OVERRIDE; virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE; virtual void PrepareForShutdown() OVERRIDE; diff --git a/chromium/ui/aura/root_window_host_x11.cc b/chromium/ui/aura/root_window_host_x11.cc index f69a54a8898..abf1da06b9d 100644 --- a/chromium/ui/aura/root_window_host_x11.cc +++ b/chromium/ui/aura/root_window_host_x11.cc @@ -20,14 +20,11 @@ #include "base/command_line.h" #include "base/debug/trace_event.h" #include "base/message_loop/message_loop.h" -#include "base/message_loop/message_pump_aurax11.h" +#include "base/message_loop/message_pump_x11.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkPostConfig.h" #include "ui/aura/client/capture_client.h" #include "ui/aura/client/cursor_client.h" #include "ui/aura/client/screen_position_client.h" @@ -35,9 +32,6 @@ #include "ui/aura/env.h" #include "ui/aura/root_window.h" #include "ui/base/cursor/cursor.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_utils.h" -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/base/touch/touch_factory_x11.h" #include "ui/base/ui_base_switches.h" #include "ui/base/view_prop.h" @@ -45,7 +39,9 @@ #include "ui/base/x/x11_util.h" #include "ui/compositor/dip_util.h" #include "ui/compositor/layer.h" -#include "ui/gfx/codec/png_codec.h" +#include "ui/events/event.h" +#include "ui/events/event_utils.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/screen.h" #if defined(OS_CHROMEOS) @@ -91,7 +87,7 @@ bool IsSideBezelsEnabled() { #endif void SelectEventsForRootWindow() { - Display* display = ui::GetXDisplay(); + XDisplay* display = gfx::GetXDisplay(); ::Window root_window = ui::GetX11RootWindow(); // Receive resize events for the root-window so |x_root_bounds_| can be @@ -367,7 +363,7 @@ class RootWindowHostX11::MouseMoveFilter { RootWindowHostX11::RootWindowHostX11(const gfx::Rect& bounds) : delegate_(NULL), - xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()), + xdisplay_(gfx::GetXDisplay()), xwindow_(0), x_root_window_(DefaultRootWindow(xdisplay_)), current_cursor_(ui::kCursorNull), @@ -377,7 +373,8 @@ RootWindowHostX11::RootWindowHostX11(const gfx::Rect& bounds) focus_when_shown_(false), touch_calibrate_(new internal::TouchEventCalibrate), mouse_move_filter_(new MouseMoveFilter), - atom_cache_(xdisplay_, kAtomsToCache) { + atom_cache_(xdisplay_, kAtomsToCache), + bezel_tracking_ids_(0) { XSetWindowAttributes swa; memset(&swa, 0, sizeof(swa)); swa.background_pixmap = None; @@ -391,8 +388,8 @@ RootWindowHostX11::RootWindowHostX11(const gfx::Rect& bounds) CopyFromParent, // visual CWBackPixmap | CWOverrideRedirect, &swa); - base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_); - base::MessagePumpAuraX11::Current()->AddDispatcherForRootWindow(this); + base::MessagePumpX11::Current()->AddDispatcherForWindow(this, xwindow_); + base::MessagePumpX11::Current()->AddDispatcherForRootWindow(this); long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | KeyPressMask | KeyReleaseMask | @@ -443,8 +440,8 @@ RootWindowHostX11::RootWindowHostX11(const gfx::Rect& bounds) RootWindowHostX11::~RootWindowHostX11() { Env::GetInstance()->RemoveObserver(this); - base::MessagePumpAuraX11::Current()->RemoveDispatcherForRootWindow(this); - base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_); + base::MessagePumpX11::Current()->RemoveDispatcherForRootWindow(this); + base::MessagePumpX11::Current()->RemoveDispatcherForWindow(xwindow_); UnConfineCursor(); @@ -633,7 +630,7 @@ void RootWindowHostX11::Show() { // We now block until our window is mapped. Some X11 APIs will crash and // burn if passed |xwindow_| before the window is mapped, and XMapWindow is // asynchronous. - base::MessagePumpAuraX11::Current()->BlockUntilWindowMapped(xwindow_); + base::MessagePumpX11::Current()->BlockUntilWindowMapped(xwindow_); window_mapped_ = true; } } @@ -819,51 +816,6 @@ void RootWindowHostX11::SetFocusWhenShown(bool focus_when_shown) { } } -bool RootWindowHostX11::CopyAreaToSkCanvas(const gfx::Rect& source_bounds, - const gfx::Point& dest_offset, - SkCanvas* canvas) { - ui::XScopedImage scoped_image( - XGetImage(xdisplay_, xwindow_, - source_bounds.x(), source_bounds.y(), - source_bounds.width(), source_bounds.height(), - AllPlanes, ZPixmap)); - XImage* image = scoped_image.get(); - if (!image) { - LOG(ERROR) << "XGetImage failed"; - return false; - } - - if (image->bits_per_pixel == 32) { - if ((0xff << SK_R32_SHIFT) != image->red_mask || - (0xff << SK_G32_SHIFT) != image->green_mask || - (0xff << SK_B32_SHIFT) != image->blue_mask) { - LOG(WARNING) << "XImage and Skia byte orders differ"; - return false; - } - - // Set the alpha channel before copying to the canvas. Otherwise, areas of - // the framebuffer that were cleared by ply-image rather than being obscured - // by an image during boot may end up transparent. - // TODO(derat|marcheu): Remove this if/when ply-image has been updated to - // set the framebuffer's alpha channel regardless of whether the device - // claims to support alpha or not. - for (int i = 0; i < image->width * image->height * 4; i += 4) - image->data[i + 3] = 0xff; - - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, - image->width, image->height, - image->bytes_per_line); - bitmap.setPixels(image->data); - canvas->drawBitmap(bitmap, SkIntToScalar(0), SkIntToScalar(0), NULL); - } else { - NOTIMPLEMENTED() << "Unsupported bits-per-pixel " << image->bits_per_pixel; - return false; - } - - return true; -} - void RootWindowHostX11::PostNativeEvent( const base::NativeEvent& native_event) { DCHECK(xwindow_); @@ -902,7 +854,7 @@ void RootWindowHostX11::OnDeviceScaleFactorChanged( } void RootWindowHostX11::PrepareForShutdown() { - base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_); + base::MessagePumpX11::Current()->RemoveDispatcherForWindow(xwindow_); } void RootWindowHostX11::OnWindowInitialized(Window* window) { @@ -961,15 +913,22 @@ void RootWindowHostX11::DispatchXI2Event(const base::NativeEvent& event) { case ui::ET_TOUCH_PRESSED: case ui::ET_TOUCH_CANCELLED: case ui::ET_TOUCH_RELEASED: { + ui::TouchEvent touchev(xev); #if defined(USE_XI2_MT) - // Ignore events from the bezel when the side bezel flag is not explicitly - // enabled. - if (!IsSideBezelsEnabled() && - touch_calibrate_->IsEventOnSideBezels(xev, bounds_)) { - break; + // Ignore touch events with touch press happening on the side bezel. + if (!IsSideBezelsEnabled()) { + uint32 tracking_id = (1 << touchev.touch_id()); + if (type == ui::ET_TOUCH_PRESSED && + touch_calibrate_->IsEventOnSideBezels(xev, bounds_)) + bezel_tracking_ids_ |= tracking_id; + if (bezel_tracking_ids_ & tracking_id) { + if (type == ui::ET_TOUCH_CANCELLED || type == ui::ET_TOUCH_RELEASED) + bezel_tracking_ids_ = + (bezel_tracking_ids_ | tracking_id) ^ tracking_id; + return; + } } #endif // defined(USE_XI2_MT) - ui::TouchEvent touchev(xev); #if defined(OS_CHROMEOS) if (base::chromeos::IsRunningOnChromeOS()) { if (!bounds_.Contains(touchev.location())) @@ -1131,7 +1090,7 @@ RootWindowHost* RootWindowHost::Create(const gfx::Rect& bounds) { // static gfx::Size RootWindowHost::GetNativeScreenSize() { - ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay(); + ::XDisplay* xdisplay = gfx::GetXDisplay(); return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); } diff --git a/chromium/ui/aura/root_window_host_x11.h b/chromium/ui/aura/root_window_host_x11.h index c38002dda07..77d97b90efa 100644 --- a/chromium/ui/aura/root_window_host_x11.h +++ b/chromium/ui/aura/root_window_host_x11.h @@ -63,9 +63,6 @@ class RootWindowHostX11 : public RootWindowHost, virtual void OnCursorVisibilityChanged(bool show) OVERRIDE; virtual void MoveCursorTo(const gfx::Point& location) OVERRIDE; virtual void SetFocusWhenShown(bool focus_when_shown) OVERRIDE; - virtual bool CopyAreaToSkCanvas(const gfx::Rect& source_bounds, - const gfx::Point& dest_offset, - SkCanvas* canvas) OVERRIDE; virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE; virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE; virtual void PrepareForShutdown() OVERRIDE; @@ -106,7 +103,7 @@ class RootWindowHostX11 : public RootWindowHost, RootWindowHostDelegate* delegate_; // The display and the native X window hosting the root window. - Display* xdisplay_; + XDisplay* xdisplay_; ::Window xwindow_; // The native root window. @@ -141,6 +138,9 @@ class RootWindowHostX11 : public RootWindowHost, ui::X11AtomCache atom_cache_; + // Touch ids of which the touch press happens at side bezel region. + uint32 bezel_tracking_ids_; + DISALLOW_COPY_AND_ASSIGN(RootWindowHostX11); }; diff --git a/chromium/ui/aura/root_window_mac.h b/chromium/ui/aura/root_window_mac.h deleted file mode 100644 index 13a044c21d2..00000000000 --- a/chromium/ui/aura/root_window_mac.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef UI_AURA_ROOT_WINDOW_MAC_H_ -#define UI_AURA_ROOT_WINDOW_MAC_H_ - -#import <Cocoa/Cocoa.h> - -namespace aura { -class RootWindowHostMacDelegate; -} // aura - -// RootWindow routes NSWindow events back to the RootWindowHost for dispatch -// to the Aura event handling system. -@interface RootWindowMac : NSWindow { - @private - // Weak. May be NULL. The host delegate acts as a conduit for event routing - // back to the host. - aura::RootWindowHostMacDelegate* hostDelegate_; -} - -// Designated initializer. -- (id)initWithContentRect:(NSRect)contentRect - styleMask:(NSUInteger)windowStyle - backing:(NSBackingStoreType)bufferingType - defer:(BOOL)deferCreation; - -// Sets the |hostDelegate_| -- (void)setHostDelegate:(aura::RootWindowHostMacDelegate*)hostDelegate; - -// Overrides main event dispatch to route NSWindow events to host delegate. -- (void)sendEvent:(NSEvent*)event; - -@end - -#endif // UI_AURA_ROOT_WINDOW_MAC_H_ diff --git a/chromium/ui/aura/root_window_mac.mm b/chromium/ui/aura/root_window_mac.mm deleted file mode 100644 index 32e42b7ad9d..00000000000 --- a/chromium/ui/aura/root_window_mac.mm +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2012 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. - -#import "ui/aura/root_window_mac.h" - -#include "ui/aura/root_window_host_mac.h" - -@implementation RootWindowMac - -- (id)initWithContentRect:(NSRect)contentRect - styleMask:(NSUInteger)windowStyle - backing:(NSBackingStoreType)bufferingType - defer:(BOOL)deferCreation { - if ((self = [super initWithContentRect:contentRect - styleMask:windowStyle - backing:bufferingType - defer:deferCreation])) { - hostDelegate_ = NULL; - } - return self; -} - -- (void)setHostDelegate:(aura::RootWindowHostMacDelegate*)hostDelegate { - hostDelegate_ = hostDelegate; -} - -- (void)sendEvent:(NSEvent*)event { - // Allow both the Cocoa machinery and the Aura machinery to handle the event. - [super sendEvent:event]; - if (hostDelegate_) - hostDelegate_->SendEvent(event); -} - -@end diff --git a/chromium/ui/aura/root_window_unittest.cc b/chromium/ui/aura/root_window_unittest.cc index 739de66811f..652562b2604 100644 --- a/chromium/ui/aura/root_window_unittest.cc +++ b/chromium/ui/aura/root_window_unittest.cc @@ -17,12 +17,12 @@ #include "ui/aura/test/test_window_delegate.h" #include "ui/aura/test/test_windows.h" #include "ui/aura/window_tracker.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_handler.h" -#include "ui/base/events/event_utils.h" #include "ui/base/gestures/gesture_configuration.h" #include "ui/base/hit_test.h" -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/event.h" +#include "ui/events/event_handler.h" +#include "ui/events/event_utils.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/point.h" #include "ui/gfx/rect.h" #include "ui/gfx/screen.h" @@ -402,11 +402,15 @@ namespace { class EventFilterRecorder : public ui::EventHandler { public: typedef std::vector<ui::EventType> Events; + typedef std::vector<gfx::Point> MouseEventLocations; EventFilterRecorder() {} Events& events() { return events_; } + MouseEventLocations& mouse_locations() { return mouse_locations_; } + gfx::Point mouse_location(int i) const { return mouse_locations_[i]; } + // ui::EventHandler overrides: virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE { events_.push_back(event->type()); @@ -414,6 +418,7 @@ class EventFilterRecorder : public ui::EventHandler { virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE { events_.push_back(event->type()); + mouse_locations_.push_back(event->location()); } virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE { @@ -430,6 +435,7 @@ class EventFilterRecorder : public ui::EventHandler { private: Events events_; + MouseEventLocations mouse_locations_; DISALLOW_COPY_AND_ASSIGN(EventFilterRecorder); }; @@ -679,6 +685,41 @@ TEST_F(RootWindowTest, DispatchSyntheticMouseEvents) { EXPECT_TRUE(filter->events().empty()); } +// Tests that a mouse exit is dispatched to the last known cursor location +// when the cursor becomes invisible. +TEST_F(RootWindowTest, DispatchMouseExitWhenCursorHidden) { + EventFilterRecorder* filter = new EventFilterRecorder; + root_window()->SetEventFilter(filter); // passes ownership + + test::TestWindowDelegate delegate; + gfx::Point window_origin(7, 18); + scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate( + &delegate, 1234, gfx::Rect(window_origin, + gfx::Size(100, 100)), root_window())); + window->Show(); + + // Dispatch a mouse move event into the window. + gfx::Point mouse_location(gfx::Point(15, 25)); + ui::MouseEvent mouse1(ui::ET_MOUSE_MOVED, mouse_location, + mouse_location, 0); + EXPECT_TRUE(filter->events().empty()); + root_window()->AsRootWindowHostDelegate()->OnHostMouseEvent(&mouse1); + EXPECT_FALSE(filter->events().empty()); + filter->events().clear(); + + // Hide the cursor and verify a mouse exit was dispatched. + root_window()->OnCursorVisibilityChanged(false); + EXPECT_FALSE(filter->events().empty()); + EXPECT_EQ("MOUSE_EXITED", EventTypesToString(filter->events())); + + // Verify the mouse exit was dispatched at the correct location + // (in the correct coordinate space). + int translated_x = mouse_location.x() - window_origin.x(); + int translated_y = mouse_location.y() - window_origin.y(); + gfx::Point translated_point(translated_x, translated_y); + EXPECT_EQ(filter->mouse_location(0).ToString(), translated_point.ToString()); +} + class DeletingEventFilter : public ui::EventHandler { public: DeletingEventFilter() @@ -882,4 +923,132 @@ TEST_F(RootWindowTest, GestureEndDeliveredAfterNestedGestures) { EXPECT_EQ(1, d2.gesture_end_count()); } +// Tests whether we can repost the Tap down gesture event. +TEST_F(RootWindowTest, RepostTapdownGestureTest) { + EventFilterRecorder* filter = new EventFilterRecorder; + root_window()->SetEventFilter(filter); // passes ownership + + test::TestWindowDelegate delegate; + scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate( + &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window())); + + ui::GestureEventDetails details(ui::ET_GESTURE_TAP_DOWN, 0.0f, 0.0f); + gfx::Point point(10, 10); + ui::GestureEvent event( + ui::ET_GESTURE_TAP_DOWN, + point.x(), + point.y(), + 0, + ui::EventTimeForNow(), + details, + 0); + root_window()->RepostEvent(event); + RunAllPendingInMessageLoop(); + // TODO(rbyers): Currently disabled - crbug.com/170987 + EXPECT_FALSE(EventTypesToString(filter->events()).find("GESTURE_TAP_DOWN") != + std::string::npos); + filter->events().clear(); +} + +// This class inherits from the EventFilterRecorder class which provides a +// facility to record events. This class additionally provides a facility to +// repost the ET_GESTURE_TAP_DOWN gesture to the target window and records +// events after that. +class RepostGestureEventRecorder : public EventFilterRecorder { + public: + RepostGestureEventRecorder(aura::Window* repost_source, + aura::Window* repost_target) + : repost_source_(repost_source), + repost_target_(repost_target), + reposted_(false) {} + + virtual ~RepostGestureEventRecorder() {} + + virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { + EXPECT_EQ(reposted_ ? repost_target_ : repost_source_, event->target()); + if (event->type() == ui::ET_GESTURE_TAP_DOWN) { + if (!reposted_) { + EXPECT_NE(repost_target_, event->target()); + reposted_ = true; + events().clear(); + repost_target_->GetRootWindow()->RepostEvent(*event); + // Ensure that the reposted gesture event above goes to the + // repost_target_; + repost_source_->GetRootWindow()->RemoveChild(repost_source_); + return; + } + } + EventFilterRecorder::OnGestureEvent(event); + } + + // Ignore mouse events as they don't fire at all times. This causes + // the GestureRepostEventOrder test to fail randomly. + virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {} + + private: + aura::Window* repost_source_; + aura::Window* repost_target_; + // set to true if we reposted the ET_GESTURE_TAP_DOWN event. + bool reposted_; + DISALLOW_COPY_AND_ASSIGN(RepostGestureEventRecorder); +}; + +// Tests whether events which are generated after the reposted gesture event +// are received after that. In this case the scroll sequence events should +// be received after the reposted gesture event. +TEST_F(RootWindowTest, GestureRepostEventOrder) { + // Expected events at the end for the repost_target window defined below. + const char kExpectedTargetEvents[] = + // TODO)(rbyers): Gesture event reposting is disabled - crbug.com/279039. + // "GESTURE_BEGIN GESTURE_TAP_DOWN " + "TOUCH_RELEASED TOUCH_PRESSED GESTURE_BEGIN GESTURE_TAP_DOWN TOUCH_MOVED " + " GESTURE_SCROLL_BEGIN GESTURE_SCROLL_UPDATE TOUCH_MOVED " + "GESTURE_SCROLL_UPDATE TOUCH_MOVED GESTURE_SCROLL_UPDATE TOUCH_RELEASED " + "GESTURE_SCROLL_END GESTURE_END"; + // We create two windows. + // The first window (repost_source) is the one to which the initial tap + // gesture is sent. It reposts this event to the second window + // (repost_target). + // We then generate the scroll sequence for repost_target and look for two + // ET_GESTURE_TAP_DOWN events in the event list at the end. + test::TestWindowDelegate delegate; + scoped_ptr<aura::Window> repost_target(CreateTestWindowWithDelegate( + &delegate, 1, gfx::Rect(0, 0, 100, 100), root_window())); + + scoped_ptr<aura::Window> repost_source(CreateTestWindowWithDelegate( + &delegate, 1, gfx::Rect(0, 0, 50, 50), root_window())); + + RepostGestureEventRecorder* repost_event_recorder = + new RepostGestureEventRecorder(repost_source.get(), repost_target.get()); + root_window()->SetEventFilter(repost_event_recorder); // passes ownership + + // Generate a tap down gesture for the repost_source. This will be reposted + // to repost_target. + test::EventGenerator repost_generator(root_window(), repost_source.get()); + repost_generator.GestureTapAt(gfx::Point(40, 40)); + RunAllPendingInMessageLoop(); + + test::EventGenerator scroll_generator(root_window(), repost_target.get()); + scroll_generator.GestureScrollSequence( + gfx::Point(80, 80), + gfx::Point(100, 100), + base::TimeDelta::FromMilliseconds(100), + 3); + RunAllPendingInMessageLoop(); + + int tap_down_count = 0; + for (size_t i = 0; i < repost_event_recorder->events().size(); ++i) { + if (repost_event_recorder->events()[i] == ui::ET_GESTURE_TAP_DOWN) + ++tap_down_count; + } + + // We expect two tap down events. One from the repost and the other one from + // the scroll sequence posted above. + // TODO(rbyers): Currently disabled - crbug.com/170987 + EXPECT_EQ(1, tap_down_count); + + EXPECT_EQ(kExpectedTargetEvents, + EventTypesToString(repost_event_recorder->events())); +} + } // namespace aura diff --git a/chromium/ui/aura/root_window_view_mac.h b/chromium/ui/aura/root_window_view_mac.h deleted file mode 100644 index 6617f36dad9..00000000000 --- a/chromium/ui/aura/root_window_view_mac.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef UI_AURA_ROOT_WINDOW_VIEW_MAC_H_ -#define UI_AURA_ROOT_WINDOW_VIEW_MAC_H_ - -#import <Cocoa/Cocoa.h> - -#include "ui/compositor/compositor.h" - -// RootWindowView provides an NSView class that delegates drawing to a -// ui::Compositor delegate, setting up the NSOpenGLContext as required. -@interface RootWindowView : NSView { - @private - ui::Compositor* compositor_; -} --(void)setCompositor:(ui::Compositor*)compositor; -@end - -#endif // UI_AURA_ROOT_WINDOW_VIEW_MAC_H_ diff --git a/chromium/ui/aura/root_window_view_mac.mm b/chromium/ui/aura/root_window_view_mac.mm deleted file mode 100644 index a82100e8434..00000000000 --- a/chromium/ui/aura/root_window_view_mac.mm +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2012 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. - -#import "ui/aura/root_window_view_mac.h" - -@implementation RootWindowView --(void)setCompositor:(ui::Compositor*)compositor { - compositor_ = compositor; -} - -- (void)drawRect:(NSRect)rect { - if (compositor_) - compositor_->Draw(false); -} -@end diff --git a/chromium/ui/aura/window.cc b/chromium/ui/aura/window.cc index e5289e46a29..b14048287c6 100644 --- a/chromium/ui/aura/window.cc +++ b/chromium/ui/aura/window.cc @@ -25,24 +25,15 @@ #include "ui/aura/window_delegate.h" #include "ui/aura/window_observer.h" #include "ui/aura/window_tracker.h" -#include "ui/base/animation/multi_animation.h" #include "ui/compositor/compositor.h" #include "ui/compositor/layer.h" +#include "ui/gfx/animation/multi_animation.h" #include "ui/gfx/canvas.h" #include "ui/gfx/path.h" #include "ui/gfx/screen.h" namespace aura { -namespace { - -void MailboxReleaseCallback(scoped_ptr<base::SharedMemory> shared_memory, - unsigned sync_point, bool lost_resource) { - // NOTE: shared_memory will get released when we go out of scope. -} - -} // namespace - Window::Window(WindowDelegate* delegate) : type_(client::WINDOW_TYPE_UNKNOWN), owned_by_parent_(true), @@ -154,12 +145,6 @@ ui::Layer* Window::RecreateLayer() { return NULL; old_layer->set_delegate(NULL); - float mailbox_scale_factor; - cc::TextureMailbox old_mailbox = - old_layer->GetTextureMailbox(&mailbox_scale_factor); - scoped_refptr<ui::Texture> old_texture = old_layer->external_texture(); - if (delegate_ && old_texture.get()) - old_layer->SetExternalTexture(delegate_->CopyTexture().get()); layer_ = new ui::Layer(old_layer->type()); layer_owner_.reset(layer_); @@ -167,29 +152,9 @@ ui::Layer* Window::RecreateLayer() { layer_->set_scale_content(old_layer->scale_content()); layer_->set_delegate(this); layer_->SetMasksToBounds(old_layer->GetMasksToBounds()); - // Move the original texture to the new layer if the old layer has a - // texture and we could copy it into the old layer, - // crbug.com/175211. - if (delegate_ && old_texture.get()) { - layer_->SetExternalTexture(old_texture.get()); - } else if (old_mailbox.IsSharedMemory()) { - base::SharedMemory* old_buffer = old_mailbox.shared_memory(); - const size_t size = old_mailbox.shared_memory_size_in_bytes(); - - scoped_ptr<base::SharedMemory> new_buffer(new base::SharedMemory); - new_buffer->CreateAndMapAnonymous(size); - - if (old_buffer->memory() && new_buffer->memory()) { - memcpy(new_buffer->memory(), old_buffer->memory(), size); - base::SharedMemory* new_buffer_raw_ptr = new_buffer.get(); - cc::TextureMailbox::ReleaseCallback callback = - base::Bind(MailboxReleaseCallback, Passed(&new_buffer)); - cc::TextureMailbox new_mailbox(new_buffer_raw_ptr, - old_mailbox.shared_memory_size(), - callback); - layer_->SetTextureMailbox(new_mailbox, mailbox_scale_factor); - } - } + + if (delegate_) + delegate_->DidRecreateLayer(old_layer, layer_); UpdateLayerName(name_); layer_->SetFillsBoundsOpaquely(!transparent_); @@ -224,9 +189,9 @@ void Window::SetName(const std::string& name) { } void Window::SetTransparent(bool transparent) { - // Cannot change transparent flag after the window is initialized. - DCHECK(!layer()); transparent_ = transparent; + if (layer()) + layer_->SetFillsBoundsOpaquely(!transparent_); } RootWindow* Window::GetRootWindow() { diff --git a/chromium/ui/aura/window.h b/chromium/ui/aura/window.h index 92dfa90b9c4..3ed7ca5cdff 100644 --- a/chromium/ui/aura/window.h +++ b/chromium/ui/aura/window.h @@ -17,13 +17,13 @@ #include "ui/aura/aura_export.h" #include "ui/aura/client/window_types.h" #include "ui/aura/window_observer.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/events/event_target.h" #include "ui/base/gestures/gesture_types.h" #include "ui/compositor/layer_animator.h" #include "ui/compositor/layer_delegate.h" #include "ui/compositor/layer_owner.h" #include "ui/compositor/layer_type.h" +#include "ui/events/event_constants.h" +#include "ui/events/event_target.h" #include "ui/gfx/insets.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/rect.h" diff --git a/chromium/ui/aura/window_delegate.h b/chromium/ui/aura/window_delegate.h index bcbd2a6984c..ff941ef95b3 100644 --- a/chromium/ui/aura/window_delegate.h +++ b/chromium/ui/aura/window_delegate.h @@ -8,8 +8,8 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" #include "ui/aura/aura_export.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/events/event_handler.h" +#include "ui/events/event_constants.h" +#include "ui/events/event_handler.h" #include "ui/gfx/native_widget_types.h" namespace gfx { @@ -23,6 +23,7 @@ class Size; namespace ui { class GestureEvent; class KeyEvent; +class Layer; class MouseEvent; class Texture; class TouchEvent; @@ -95,9 +96,12 @@ class AURA_EXPORT WindowDelegate : public ui::EventHandler { // above returns true. virtual void GetHitTestMask(gfx::Path* mask) const = 0; - // Called from RecreateLayer() if the layer the window is associated with has - // an external texture. - virtual scoped_refptr<ui::Texture> CopyTexture() = 0; + // Called from RecreateLayer() after the new layer was created. old_layer is + // the layer that will be returned to the caller of RecreateLayer, new_layer + // will be the layer now used on the Window. The implementation only has to do + // anything if the layer has external content (SetExternalTexture / + // SetTextureMailbox / SetDelegatedFrame was called). + virtual void DidRecreateLayer(ui::Layer* old_layer, ui::Layer* new_layer) = 0; protected: virtual ~WindowDelegate() {} diff --git a/chromium/ui/aura/window_unittest.cc b/chromium/ui/aura/window_unittest.cc index 320d1a61f7b..c37eb833cc9 100644 --- a/chromium/ui/aura/window_unittest.cc +++ b/chromium/ui/aura/window_unittest.cc @@ -27,15 +27,15 @@ #include "ui/aura/window_delegate.h" #include "ui/aura/window_observer.h" #include "ui/aura/window_property.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_utils.h" #include "ui/base/gestures/gesture_configuration.h" #include "ui/base/hit_test.h" -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/compositor/layer.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/compositor/test/test_layers.h" +#include "ui/events/event.h" +#include "ui/events/event_utils.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/canvas.h" #include "ui/gfx/screen.h" @@ -1780,7 +1780,7 @@ TEST_F(WindowTest, SetBoundsInternalShouldCheckTargetBounds) { EXPECT_FALSE(!w1->layer()); w1->layer()->GetAnimator()->set_disable_timer_for_test(true); - ui::AnimationContainerElement* element = w1->layer()->GetAnimator(); + gfx::AnimationContainerElement* element = w1->layer()->GetAnimator(); EXPECT_EQ("0,0 100x100", w1->bounds().ToString()); EXPECT_EQ("0,0 100x100", w1->layer()->GetTargetBounds().ToString()); @@ -2740,7 +2740,7 @@ TEST_F(WindowTest, DelegateNotifiedAsBoundsChange) { // Animate to the end, which should notify of the change. base::TimeTicks start_time = window->layer()->GetAnimator()->last_step_time(); - ui::AnimationContainerElement* element = window->layer()->GetAnimator(); + gfx::AnimationContainerElement* element = window->layer()->GetAnimator(); element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); EXPECT_TRUE(delegate.bounds_changed()); EXPECT_NE("0,0 100x100", window->bounds().ToString()); @@ -2782,7 +2782,7 @@ TEST_F(WindowTest, DelegateNotifiedAsBoundsChangeInHiddenLayer) { // Animate to the end: will *not* notify of the change since we are hidden. base::TimeTicks start_time = window->layer()->GetAnimator()->last_step_time(); - ui::AnimationContainerElement* element = window->layer()->GetAnimator(); + gfx::AnimationContainerElement* element = window->layer()->GetAnimator(); element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); // No bounds changed notification at the end of animation since layer diff --git a/chromium/ui/base/accelerators/accelerator.cc b/chromium/ui/base/accelerators/accelerator.cc index fbb60a796b4..4439af51dbe 100644 --- a/chromium/ui/base/accelerators/accelerator.cc +++ b/chromium/ui/base/accelerators/accelerator.cc @@ -18,7 +18,7 @@ #include "ui/base/l10n/l10n_util.h" #if !defined(OS_WIN) && (defined(USE_AURA) || defined(OS_MACOSX)) -#include "ui/base/keycodes/keyboard_code_conversion.h" +#include "ui/events/keycodes/keyboard_code_conversion.h" #endif namespace ui { @@ -155,6 +155,18 @@ base::string16 Accelerator::GetShortcutText() const { case ui::VKEY_OEM_PERIOD: string_id = IDS_APP_PERIOD_KEY; break; + case ui::VKEY_MEDIA_NEXT_TRACK: + string_id = IDS_APP_MEDIA_NEXT_TRACK_KEY; + break; + case ui::VKEY_MEDIA_PLAY_PAUSE: + string_id = IDS_APP_MEDIA_PLAY_PAUSE_KEY; + break; + case ui::VKEY_MEDIA_PREV_TRACK: + string_id = IDS_APP_MEDIA_PREV_TRACK_KEY; + break; + case ui::VKEY_MEDIA_STOP: + string_id = IDS_APP_MEDIA_STOP_KEY; + break; default: break; } diff --git a/chromium/ui/base/accelerators/accelerator.h b/chromium/ui/base/accelerators/accelerator.h index e86538c529f..020c7bea40c 100644 --- a/chromium/ui/base/accelerators/accelerator.h +++ b/chromium/ui/base/accelerators/accelerator.h @@ -14,9 +14,9 @@ #include "base/memory/scoped_ptr.h" #include "base/strings/string16.h" #include "ui/base/accelerators/platform_accelerator.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/base/ui_export.h" +#include "ui/events/event_constants.h" +#include "ui/events/keycodes/keyboard_codes.h" namespace ui { diff --git a/chromium/ui/base/accelerators/accelerator_manager.h b/chromium/ui/base/accelerators/accelerator_manager.h index 2e6645ee996..818dc3ea05a 100644 --- a/chromium/ui/base/accelerators/accelerator_manager.h +++ b/chromium/ui/base/accelerators/accelerator_manager.h @@ -11,8 +11,8 @@ #include "base/basictypes.h" #include "ui/base/accelerators/accelerator.h" -#include "ui/base/events/event_constants.h" #include "ui/base/ui_export.h" +#include "ui/events/event_constants.h" namespace ui { diff --git a/chromium/ui/base/accelerators/accelerator_manager_unittest.cc b/chromium/ui/base/accelerators/accelerator_manager_unittest.cc index 73d1a1d0719..b8672ec1462 100644 --- a/chromium/ui/base/accelerators/accelerator_manager_unittest.cc +++ b/chromium/ui/base/accelerators/accelerator_manager_unittest.cc @@ -6,8 +6,8 @@ #include "base/compiler_specific.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/event_constants.h" +#include "ui/events/keycodes/keyboard_codes.h" namespace ui { namespace test { diff --git a/chromium/ui/base/accelerators/platform_accelerator_gtk.cc b/chromium/ui/base/accelerators/platform_accelerator_gtk.cc index cae259b6d65..5662452a530 100644 --- a/chromium/ui/base/accelerators/platform_accelerator_gtk.cc +++ b/chromium/ui/base/accelerators/platform_accelerator_gtk.cc @@ -4,11 +4,36 @@ #include "ui/base/accelerators/platform_accelerator_gtk.h" -#include "ui/base/events/event_conversion_gtk.h" -#include "ui/base/keycodes/keyboard_code_conversion_gtk.h" +#include "ui/events/keycodes/keyboard_code_conversion_gtk.h" namespace ui { +namespace { + +int GdkModifierToEventFlag(GdkModifierType gdk_modifier) { + int event_flags = 0; + if (gdk_modifier & GDK_SHIFT_MASK) + event_flags |= EF_SHIFT_DOWN; + if (gdk_modifier & GDK_CONTROL_MASK) + event_flags |= EF_CONTROL_DOWN; + if (gdk_modifier & GDK_MOD1_MASK) + event_flags |= EF_ALT_DOWN; + return event_flags; +} + +GdkModifierType EventFlagToGdkModifier(int event_flag) { + int modifier = 0; + if (event_flag & EF_SHIFT_DOWN) + modifier |= GDK_SHIFT_MASK; + if (event_flag & EF_CONTROL_DOWN) + modifier |= GDK_CONTROL_MASK; + if (event_flag & EF_ALT_DOWN) + modifier |= GDK_MOD1_MASK; + return static_cast<GdkModifierType>(modifier); +} + +} // namespace + PlatformAcceleratorGtk::PlatformAcceleratorGtk() : gdk_key_code_(0), gdk_modifier_(static_cast<GdkModifierType>(0)) { diff --git a/chromium/ui/base/accessibility/accessible_text_utils.cc b/chromium/ui/base/accessibility/accessible_text_utils.cc index 72ab60e7b42..5fab22e120a 100644 --- a/chromium/ui/base/accessibility/accessible_text_utils.cc +++ b/chromium/ui/base/accessibility/accessible_text_utils.cc @@ -9,7 +9,7 @@ namespace ui { -size_t FindAccessibleTextBoundary(const string16& text, +size_t FindAccessibleTextBoundary(const base::string16& text, const std::vector<int>& line_breaks, TextBoundaryType boundary, size_t start_offset, diff --git a/chromium/ui/base/accessibility/accessible_text_utils.h b/chromium/ui/base/accessibility/accessible_text_utils.h index 479e719087e..a64088c7f94 100644 --- a/chromium/ui/base/accessibility/accessible_text_utils.h +++ b/chromium/ui/base/accessibility/accessible_text_utils.h @@ -42,7 +42,7 @@ enum TextBoundaryDirection { // (depending on |direction|) from the given |start_offset| until the // given boundary is found, and return the offset of that boundary, // using the vector of line break character offsets in |line_breaks|. -size_t UI_EXPORT FindAccessibleTextBoundary(const string16& text, +size_t UI_EXPORT FindAccessibleTextBoundary(const base::string16& text, const std::vector<int>& line_breaks, TextBoundaryType boundary, size_t start_offset, diff --git a/chromium/ui/base/accessibility/accessible_view_state.h b/chromium/ui/base/accessibility/accessible_view_state.h index 8e835ec2c63..2f4b4bffaac 100644 --- a/chromium/ui/base/accessibility/accessible_view_state.h +++ b/chromium/ui/base/accessibility/accessible_view_state.h @@ -34,16 +34,16 @@ struct UI_EXPORT AccessibleViewState { AccessibilityTypes::State state; // The view's name / label. - string16 name; + base::string16 name; // The view's value, for example the text content. - string16 value; + base::string16 value; // The name of the default action if the user clicks on this view. - string16 default_action; + base::string16 default_action; // The keyboard shortcut to activate this view, if any. - string16 keyboard_shortcut; + base::string16 keyboard_shortcut; // The selection start and end. Only applies to views with text content, // such as a text box or combo box; start and end should be -1 otherwise. diff --git a/chromium/ui/base/base_window.cc b/chromium/ui/base/base_window.cc new file mode 100644 index 00000000000..231a1771797 --- /dev/null +++ b/chromium/ui/base/base_window.cc @@ -0,0 +1,16 @@ +// 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 "ui/base/base_window.h" + +namespace ui { + +bool BaseWindow::IsRestored(const BaseWindow& window) { + return !window.IsMaximized() && + !window.IsMinimized() && + !window.IsFullscreen(); +} + +} // namespace ui + diff --git a/chromium/ui/base/base_window.h b/chromium/ui/base/base_window.h index 4f847d1eebd..d5fd2fae1c4 100644 --- a/chromium/ui/base/base_window.h +++ b/chromium/ui/base/base_window.h @@ -19,7 +19,7 @@ namespace ui { // Provides an interface to perform actions on windows, and query window // state. -class BaseWindow { +class UI_EXPORT BaseWindow { public: // Returns true if the window is currently the active/focused window. virtual bool IsActive() const = 0; @@ -33,6 +33,10 @@ class BaseWindow { // Returns true if the window is full screen. virtual bool IsFullscreen() const = 0; + // Returns true if the window is fully restored (not Fullscreen, Maximized, + // Minimized). + static bool IsRestored(const BaseWindow& window); + // Return a platform dependent identifier for this window. virtual gfx::NativeWindow GetNativeWindow() = 0; diff --git a/chromium/ui/base/clipboard/clipboard_aurax11.cc b/chromium/ui/base/clipboard/clipboard_aurax11.cc index 287941dbdab..5c6ebb8dfe3 100644 --- a/chromium/ui/base/clipboard/clipboard_aurax11.cc +++ b/chromium/ui/base/clipboard/clipboard_aurax11.cc @@ -12,10 +12,11 @@ #include "base/basictypes.h" #include "base/files/file_path.h" #include "base/logging.h" +#include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_ptr.h" #include "base/memory/singleton.h" -#include "base/message_loop/message_pump_aurax11.h" #include "base/message_loop/message_pump_observer.h" +#include "base/message_loop/message_pump_x11.h" #include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -25,7 +26,7 @@ #include "ui/base/x/selection_utils.h" #include "ui/base/x/x11_atom_cache.h" #include "ui/base/x/x11_util.h" - +#include "ui/gfx/codec/png_codec.h" #include "ui/gfx/size.h" namespace ui { @@ -33,7 +34,6 @@ namespace ui { namespace { const char kClipboard[] = "CLIPBOARD"; -const char kMimeTypeBitmap[] = "image/bmp"; const char kMimeTypeFilename[] = "chromium/filename"; const char kMimeTypePepperCustomData[] = "chromium/x-pepper-custom-data"; const char kMimeTypeWebkitSmartPaste[] = "chromium/x-webkit-paste"; @@ -41,7 +41,7 @@ const char kTargets[] = "TARGETS"; const char* kAtomsToCache[] = { kClipboard, - kMimeTypeBitmap, + Clipboard::kMimeTypePNG, kMimeTypeFilename, kMimeTypeMozillaURL, kMimeTypeWebkitSmartPaste, @@ -90,9 +90,9 @@ SelectionChangeObserver::SelectionChangeObserver() clipboard_sequence_number_(0), primary_sequence_number_(0) { int ignored; - if (XFixesQueryExtension(GetXDisplay(), &event_base_, &ignored)) { - clipboard_atom_ = XInternAtom(GetXDisplay(), kClipboard, false); - XFixesSelectSelectionInput(GetXDisplay(), GetX11RootWindow(), + if (XFixesQueryExtension(gfx::GetXDisplay(), &event_base_, &ignored)) { + clipboard_atom_ = XInternAtom(gfx::GetXDisplay(), kClipboard, false); + XFixesSelectSelectionInput(gfx::GetXDisplay(), GetX11RootWindow(), clipboard_atom_, XFixesSetSelectionOwnerNotifyMask | XFixesSelectionWindowDestroyNotifyMask | @@ -100,13 +100,13 @@ SelectionChangeObserver::SelectionChangeObserver() // This seems to be semi-optional. For some reason, registering for any // selection notify events seems to subscribe us to events for both the // primary and the clipboard buffers. Register anyway just to be safe. - XFixesSelectSelectionInput(GetXDisplay(), GetX11RootWindow(), + XFixesSelectSelectionInput(gfx::GetXDisplay(), GetX11RootWindow(), XA_PRIMARY, XFixesSetSelectionOwnerNotifyMask | XFixesSelectionWindowDestroyNotifyMask | XFixesSelectionClientCloseNotifyMask); - base::MessagePumpAuraX11::Current()->AddObserver(this); + base::MessagePumpX11::Current()->AddObserver(this); } } @@ -309,7 +309,7 @@ class Clipboard::AuraX11Details : public base::MessagePumpDispatcher { }; Clipboard::AuraX11Details::AuraX11Details() - : x_display_(GetXDisplay()), + : x_display_(gfx::GetXDisplay()), x_root_window_(DefaultRootWindow(x_display_)), x_window_(XCreateWindow( x_display_, x_root_window_, @@ -332,11 +332,11 @@ Clipboard::AuraX11Details::AuraX11Details() XStoreName(x_display_, x_window_, "Chromium clipboard"); XSelectInput(x_display_, x_window_, PropertyChangeMask); - base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, x_window_); + base::MessagePumpX11::Current()->AddDispatcherForWindow(this, x_window_); } Clipboard::AuraX11Details::~AuraX11Details() { - base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(x_window_); + base::MessagePumpX11::Current()->RemoveDispatcherForWindow(x_window_); XDestroyWindow(x_display_, x_window_); } @@ -653,7 +653,16 @@ void Clipboard::ReadRTF(Buffer buffer, std::string* result) const { SkBitmap Clipboard::ReadImage(Buffer buffer) const { DCHECK(CalledOnValidThread()); - NOTIMPLEMENTED(); + + SelectionData data(aurax11_details_->RequestAndWaitForTypes( + buffer, + aurax11_details_->GetAtomsForFormat(GetBitmapFormatType()))); + if (data.IsValid()) { + SkBitmap bitmap; + if (gfx::PNGCodec::Decode(data.GetData(), data.GetSize(), &bitmap)) + return SkBitmap(bitmap); + } + return SkBitmap(); } @@ -749,10 +758,21 @@ void Clipboard::WriteWebSmartPaste() { } void Clipboard::WriteBitmap(const char* pixel_data, const char* size_data) { - // TODO(erg): I'm not sure if we should be writting BMP data here or - // not. It's what the GTK port does, but I'm not sure it's the right thing to - // do. - NOTIMPLEMENTED(); + const gfx::Size* size = reinterpret_cast<const gfx::Size*>(size_data); + + // Adopt the pixels into a SkBitmap. Note that the pixel order in memory is + // actually BGRA. + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, size->width(), size->height()); + bitmap.setPixels(const_cast<char*>(pixel_data)); + + // Encode the bitmap as a PNG for transport. + std::vector<unsigned char> output; + if (gfx::PNGCodec::FastEncodeBGRASkBitmap(bitmap, false, &output)) { + aurax11_details_->InsertMapping(kMimeTypePNG, + base::RefCountedBytes::TakeVector( + &output)); + } } void Clipboard::WriteData(const FormatType& format, @@ -822,7 +842,7 @@ const Clipboard::FormatType& Clipboard::GetRtfFormatType() { // static const Clipboard::FormatType& Clipboard::GetBitmapFormatType() { - CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeBitmap)); + CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypePNG)); return type; } diff --git a/chromium/ui/base/clipboard/clipboard_gtk.cc b/chromium/ui/base/clipboard/clipboard_gtk.cc index 722242ae30d..86f4a3c3dc3 100644 --- a/chromium/ui/base/clipboard/clipboard_gtk.cc +++ b/chromium/ui/base/clipboard/clipboard_gtk.cc @@ -20,10 +20,10 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/clipboard/custom_data_helper.h" #include "ui/base/gtk/gtk_signal.h" -#include "ui/base/gtk/scoped_gobject.h" #include "ui/base/x/x11_util.h" #include "ui/gfx/canvas.h" #include "ui/gfx/gtk_util.h" +#include "ui/gfx/scoped_gobject.h" #include "ui/gfx/size.h" namespace ui { @@ -62,9 +62,9 @@ SelectionChangeObserver::SelectionChangeObserver() clipboard_sequence_number_(0), primary_sequence_number_(0) { int ignored; - if (XFixesQueryExtension(GetXDisplay(), &event_base_, &ignored)) { - clipboard_atom_ = XInternAtom(GetXDisplay(), "CLIPBOARD", false); - XFixesSelectSelectionInput(GetXDisplay(), GetX11RootWindow(), + if (XFixesQueryExtension(gfx::GetXDisplay(), &event_base_, &ignored)) { + clipboard_atom_ = XInternAtom(gfx::GetXDisplay(), "CLIPBOARD", false); + XFixesSelectSelectionInput(gfx::GetXDisplay(), GetX11RootWindow(), clipboard_atom_, XFixesSetSelectionOwnerNotifyMask | XFixesSelectionWindowDestroyNotifyMask | @@ -72,7 +72,7 @@ SelectionChangeObserver::SelectionChangeObserver() // This seems to be semi-optional. For some reason, registering for any // selection notify events seems to subscribe us to events for both the // primary and the clipboard buffers. Register anyway just to be safe. - XFixesSelectSelectionInput(GetXDisplay(), GetX11RootWindow(), + XFixesSelectSelectionInput(gfx::GetXDisplay(), GetX11RootWindow(), XA_PRIMARY, XFixesSetSelectionOwnerNotifyMask | XFixesSelectionWindowDestroyNotifyMask | diff --git a/chromium/ui/base/clipboard/clipboard_unittest.cc b/chromium/ui/base/clipboard/clipboard_unittest.cc index 6e7ad4cafb8..8217a601063 100644 --- a/chromium/ui/base/clipboard/clipboard_unittest.cc +++ b/chromium/ui/base/clipboard/clipboard_unittest.cc @@ -319,8 +319,6 @@ TEST_F(ClipboardTest, URLTest) { #endif } -// TODO(erg): Reenable this everywhere once linux_aura learns what bitmaps are. -#if !(defined(USE_AURA) && !defined(OS_CHROMEOS)) TEST_F(ClipboardTest, SharedBitmapTest) { unsigned int fake_bitmap[] = { 0x46155189, 0xF6A55C8D, 0x79845674, 0xFA57BD89, @@ -363,14 +361,11 @@ TEST_F(ClipboardTest, SharedBitmapTest) { EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetBitmapFormatType(), Clipboard::BUFFER_STANDARD)); } -#endif -// The following test somehow fails on GTK. The image when read back from the -// clipboard has the alpha channel set to 0xFF for some reason. The other -// channels stay intact. So I am turning this on only for aura. -// -// TODO(erg): This also crashes in linux_aura. Investigate once bitmap writing -// is implemented. +// The following test somehow fails on GTK and linux_aura. The image when read +// back from the clipboard has the alpha channel set to 0xFF for some +// reason. The other channels stay intact. So I am turning this on only for +// aura. #if (defined(USE_AURA) && !(defined(OS_WIN) || !defined(OS_CHROMEOS))) || \ defined(OS_ANDROID) TEST_F(ClipboardTest, MultipleBitmapReadWriteTest) { diff --git a/chromium/ui/base/cocoa/appkit_utils.h b/chromium/ui/base/cocoa/appkit_utils.h new file mode 100644 index 00000000000..159921bd136 --- /dev/null +++ b/chromium/ui/base/cocoa/appkit_utils.h @@ -0,0 +1,35 @@ +// 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. + +#ifndef UI_BASE_COCOA_APPKIT_UTILS_H +#define UI_BASE_COCOA_APPKIT_UTILS_H + +#import <Cocoa/Cocoa.h> + +#include "ui/base/ui_export.h" + +namespace ui { + +struct NinePartImageIds { + int top_left; + int top; + int top_right; + int left; + int center; + int right; + int bottom_left; + int bottom; + int bottom_right; +}; + +// Utility method to draw a nine part image using image ids. +UI_EXPORT void DrawNinePartImage(NSRect frame, + const NinePartImageIds& image_ids, + NSCompositingOperation operation, + CGFloat alpha, + BOOL flipped); + +} // namespace ui + +#endif // UI_BASE_COCOA_APPKIT_UTILS_H diff --git a/chromium/ui/base/cocoa/appkit_utils.mm b/chromium/ui/base/cocoa/appkit_utils.mm new file mode 100644 index 00000000000..824a6ac9256 --- /dev/null +++ b/chromium/ui/base/cocoa/appkit_utils.mm @@ -0,0 +1,41 @@ +// 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. + +#import "ui/base/cocoa/appkit_utils.h" + +#include "ui/base/resource/resource_bundle.h" + +namespace { + +// Gets an NSImage given an image id. +NSImage* GetImage(int image_id) { + return ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(image_id) + .ToNSImage(); +} + +} // namespace + +namespace ui { + +void DrawNinePartImage(NSRect frame, + const NinePartImageIds& image_ids, + NSCompositingOperation operation, + CGFloat alpha, + BOOL flipped) { + NSDrawNinePartImage(frame, + GetImage(image_ids.top_left), + GetImage(image_ids.top), + GetImage(image_ids.top_right), + GetImage(image_ids.left), + GetImage(image_ids.center), + GetImage(image_ids.right), + GetImage(image_ids.bottom_left), + GetImage(image_ids.bottom), + GetImage(image_ids.bottom_right), + operation, + alpha, + flipped); +} + +} // namespace ui diff --git a/chromium/ui/base/cocoa/cocoa_event_utils.mm b/chromium/ui/base/cocoa/cocoa_event_utils.mm index 19206992364..a8fd8c38a1c 100644 --- a/chromium/ui/base/cocoa/cocoa_event_utils.mm +++ b/chromium/ui/base/cocoa/cocoa_event_utils.mm @@ -4,7 +4,7 @@ #import "ui/base/cocoa/cocoa_event_utils.h" -#include "ui/base/events/event_constants.h" +#include "ui/events/event_constants.h" #include "ui/base/window_open_disposition.h" namespace { diff --git a/chromium/ui/base/cocoa/cocoa_event_utils_unittest.mm b/chromium/ui/base/cocoa/cocoa_event_utils_unittest.mm index cb5f68a407e..5ec3936fdcb 100644 --- a/chromium/ui/base/cocoa/cocoa_event_utils_unittest.mm +++ b/chromium/ui/base/cocoa/cocoa_event_utils_unittest.mm @@ -7,7 +7,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" #include "ui/base/cocoa/cocoa_event_utils.h" -#include "ui/base/events/event_constants.h" +#include "ui/events/event_constants.h" #import "ui/base/test/cocoa_test_event_utils.h" #import "ui/base/test/ui_cocoa_test_helper.h" diff --git a/chromium/ui/base/cocoa/controls/hyperlink_button_cell.mm b/chromium/ui/base/cocoa/controls/hyperlink_button_cell.mm index c723b03a7c3..57b70779cf3 100644 --- a/chromium/ui/base/cocoa/controls/hyperlink_button_cell.mm +++ b/chromium/ui/base/cocoa/controls/hyperlink_button_cell.mm @@ -52,6 +52,14 @@ return self; } +- (id)copyWithZone:(NSZone*)zone { + NSColor* color = textColor_.release(); + HyperlinkButtonCell* cell = [super copyWithZone:zone]; + cell->textColor_.reset([color copy]); + textColor_.reset(color); + return cell; +} + // Because an NSButtonCell has multiple initializers, this method performs the // common cell customization code. - (void)customizeButtonCell { diff --git a/chromium/ui/base/cocoa/controls/hyperlink_button_cell_unittest.mm b/chromium/ui/base/cocoa/controls/hyperlink_button_cell_unittest.mm index 479141b7234..3d24f01fa90 100644 --- a/chromium/ui/base/cocoa/controls/hyperlink_button_cell_unittest.mm +++ b/chromium/ui/base/cocoa/controls/hyperlink_button_cell_unittest.mm @@ -8,6 +8,7 @@ #include "base/mac/foundation_util.h" #include "base/mac/scoped_nsobject.h" +#import "testing/gtest_mac.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" #import "ui/base/test/ui_cocoa_test_helper.h" @@ -115,6 +116,17 @@ TEST_F(HyperlinkButtonCellTest, UnderlineOnHover) { EXPECT_FALSE(HasUnderlineAttribute([cell_ linkAttributes])); } +TEST_F(HyperlinkButtonCellTest, Copy) { + base::scoped_nsobject<HyperlinkButtonCell> cell1([[HyperlinkButtonCell alloc] + initTextCell:@"Cell"]); + [cell1 setTextColor:[NSColor redColor]]; + + base::scoped_nsobject<HyperlinkButtonCell> cell2([cell1 copy]); + EXPECT_NSEQ([cell1 textColor], [cell2 textColor]); + [cell1 setTextColor:[NSColor purpleColor]]; + [cell2 setTextColor:[NSColor greenColor]]; +} + } // namespace } // namespace ui diff --git a/chromium/ui/base/cocoa/events_mac.mm b/chromium/ui/base/cocoa/events_mac.mm index eacfb964bee..da08510a922 100644 --- a/chromium/ui/base/cocoa/events_mac.mm +++ b/chromium/ui/base/cocoa/events_mac.mm @@ -4,13 +4,13 @@ #include <Cocoa/Cocoa.h> -#include "ui/base/events/event_constants.h" +#include "ui/events/event_constants.h" #include "base/event_types.h" #include "base/logging.h" #include "base/time/time.h" -#include "ui/base/events/event_utils.h" -#import "ui/base/keycodes/keyboard_code_conversion_mac.h" +#include "ui/events/event_utils.h" +#import "ui/events/keycodes/keyboard_code_conversion_mac.h" #include "ui/gfx/point.h" namespace ui { diff --git a/chromium/ui/base/cocoa/events_mac_unittest.mm b/chromium/ui/base/cocoa/events_mac_unittest.mm index cf641c8dc7d..63f5319067e 100644 --- a/chromium/ui/base/cocoa/events_mac_unittest.mm +++ b/chromium/ui/base/cocoa/events_mac_unittest.mm @@ -5,8 +5,8 @@ #import <Cocoa/Cocoa.h> #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/events/event_utils.h" +#include "ui/events/event_constants.h" +#include "ui/events/event_utils.h" #include "ui/base/test/cocoa_test_event_utils.h" #import "ui/base/test/ui_cocoa_test_helper.h" #include "ui/gfx/point.h" diff --git a/chromium/ui/base/cocoa/focus_window_set.h b/chromium/ui/base/cocoa/focus_window_set.h index af9c25386b2..d43ff2acf97 100644 --- a/chromium/ui/base/cocoa/focus_window_set.h +++ b/chromium/ui/base/cocoa/focus_window_set.h @@ -15,7 +15,8 @@ namespace ui { // Brings a group of windows to the front without changing their order, and // makes the frontmost one key and main. If none are visible, the frontmost // miniaturized window is deminiaturized. -UI_EXPORT void FocusWindowSet(const std::set<gfx::NativeWindow>& windows); +UI_EXPORT void FocusWindowSet(const std::set<gfx::NativeWindow>& windows, + bool allow_workspace_switch); } // namespace ui diff --git a/chromium/ui/base/cocoa/focus_window_set.mm b/chromium/ui/base/cocoa/focus_window_set.mm index 553db6fe3be..e260627d3ca 100644 --- a/chromium/ui/base/cocoa/focus_window_set.mm +++ b/chromium/ui/base/cocoa/focus_window_set.mm @@ -8,25 +8,56 @@ namespace ui { -void FocusWindowSet(const std::set<NSWindow*>& windows) { +// This attempts to match OS X's native behavior, namely that a window +// is only ever deminiaturized if ALL windows on ALL workspaces are +// miniaturized. (This callback runs before AppKit picks its own +// window to deminiaturize, so we get to pick one from the right set.) +// +// In addition, limit to the windows on the current +// workspace. Otherwise we jump spaces haphazardly. +// +// NOTE: This is not perfect. If clicking the dock icon resulted in +// switching spaces, isOnActiveSpace gives the answer for the PREVIOUS +// space. This means that we actually raise the wrong space's +// windows. This seems to still work okay. +// +// However, if we decide to deminiaturize a window instead, that +// results in switching spaces and switching back. Fortunately, this +// only happens if, say, space 1 contains an app, space 2 contains a +// miniaturized browser. We click the icon, OS X switches to space 1, +// we deminiaturize the browser, and that triggers switching back. +void FocusWindowSet(const std::set<NSWindow*>& windows, + bool allow_workspace_switch) { NSArray* ordered_windows = [NSApp orderedWindows]; NSWindow* frontmost_window = nil; + NSWindow* frontmost_window_all_spaces = nil; NSWindow* frontmost_miniaturized_window = nil; + bool all_miniaturized = true; for (int i = [ordered_windows count] - 1; i >= 0; i--) { NSWindow* win = [ordered_windows objectAtIndex:i]; if (windows.find(win) != windows.end()) { - if ([win isVisible]) { - [win orderFront:nil]; - frontmost_window = win; - } else if ([win isMiniaturized]) { + if ([win isMiniaturized]) { frontmost_miniaturized_window = win; + } else if ([win isVisible]) { + all_miniaturized = false; + frontmost_window_all_spaces = win; + if ([win isOnActiveSpace]) { + [win orderFront:nil]; + frontmost_window = win; + } } } } - if (!frontmost_window && frontmost_miniaturized_window) { + if (all_miniaturized && frontmost_miniaturized_window) { [frontmost_miniaturized_window deminiaturize:nil]; frontmost_window = frontmost_miniaturized_window; } + // If we couldn't find one on this window, consider all spaces. + if (allow_workspace_switch && + !frontmost_window && frontmost_window_all_spaces) { + frontmost_window = frontmost_window_all_spaces; + [frontmost_window orderFront:nil]; + } if (frontmost_window) { [NSApp activateIgnoringOtherApps:YES]; [frontmost_window makeMainWindow]; diff --git a/chromium/ui/base/cocoa/menu_controller.mm b/chromium/ui/base/cocoa/menu_controller.mm index 1179284924b..c7b8dff2fa3 100644 --- a/chromium/ui/base/cocoa/menu_controller.mm +++ b/chromium/ui/base/cocoa/menu_controller.mm @@ -11,8 +11,9 @@ #import "ui/base/cocoa/cocoa_event_utils.h" #include "ui/base/l10n/l10n_util_mac.h" #include "ui/base/models/simple_menu_model.h" -#include "ui/base/text/text_elider.h" +#include "ui/gfx/font.h" #include "ui/gfx/image/image.h" +#include "ui/gfx/text_elider.h" @interface MenuController (Private) - (void)addSeparatorToMenu:(NSMenu*)menu @@ -29,7 +30,7 @@ NSFont* nsfont = [NSFont menuBarFontOfSize:0]; // 0 means "default" gfx::Font font(base::SysNSStringToUTF8([nsfont fontName]), static_cast<int>([nsfont pointSize])); - return ui::ElideText(title, font, width, ui::ELIDE_AT_END); + return gfx::ElideText(title, font, width, gfx::ELIDE_AT_END); } - (id)init { diff --git a/chromium/ui/base/cursor/cursor.h b/chromium/ui/base/cursor/cursor.h index 43c201db37b..bb832fa9631 100644 --- a/chromium/ui/base/cursor/cursor.h +++ b/chromium/ui/base/cursor/cursor.h @@ -82,6 +82,11 @@ const int kCursorGrab = 42; const int kCursorGrabbing = 43; const int kCursorCustom = 44; +enum CursorSetType { + CURSOR_SET_NORMAL, + CURSOR_SET_LARGE +}; + // Ref-counted cursor that supports both default and custom cursors. class UI_EXPORT Cursor { public: diff --git a/chromium/ui/base/cursor/cursor_loader_win.cc b/chromium/ui/base/cursor/cursor_loader_win.cc index 9d633f1cec8..6d35e554574 100644 --- a/chromium/ui/base/cursor/cursor_loader_win.cc +++ b/chromium/ui/base/cursor/cursor_loader_win.cc @@ -2,11 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "ui/base/cursor/cursor_loader_win.h" + #include "base/lazy_instance.h" #include "base/strings/string16.h" -#include "ui/base/cursor/cursor_loader_win.h" #include "grit/ui_unscaled_resources.h" +#if defined(USE_AURA) +#include "ui/base/cursor/cursor.h" +#endif + namespace ui { #if defined(USE_AURA) diff --git a/chromium/ui/base/cursor/cursor_loader_x11.cc b/chromium/ui/base/cursor/cursor_loader_x11.cc index e30b24cfb33..aa84173ff48 100644 --- a/chromium/ui/base/cursor/cursor_loader_x11.cc +++ b/chromium/ui/base/cursor/cursor_loader_x11.cc @@ -146,7 +146,7 @@ CursorLoader* CursorLoader::Create() { } CursorLoaderX11::CursorLoaderX11() - : invisible_cursor_(CreateInvisibleCursor(), GetXDisplay()) { + : invisible_cursor_(CreateInvisibleCursor(), gfx::GetXDisplay()) { } CursorLoaderX11::~CursorLoaderX11() { @@ -205,7 +205,7 @@ void CursorLoaderX11::LoadAnimatedCursor(int id, } animated_cursors_[id] = std::make_pair( - XcursorImagesLoadCursor(GetXDisplay(), x_images), x_images); + XcursorImagesLoadCursor(gfx::GetXDisplay(), x_images), x_images); // |bitmap| is owned by the resource bundle. So we do not need to free it. } @@ -218,7 +218,7 @@ void CursorLoaderX11::UnloadAll() { for (AnimatedCursorMap::iterator it = animated_cursors_.begin(); it != animated_cursors_.end(); ++it) { XcursorImagesDestroy(it->second.second); // also frees individual frames. - XFreeCursor(GetXDisplay(), it->second.first); + XFreeCursor(gfx::GetXDisplay(), it->second.first); } } diff --git a/chromium/ui/base/cursor/cursors_aura.cc b/chromium/ui/base/cursor/cursors_aura.cc index 17349a7c458..bb5947a57e6 100644 --- a/chromium/ui/base/cursor/cursors_aura.cc +++ b/chromium/ui/base/cursor/cursors_aura.cc @@ -5,7 +5,6 @@ #include "ui/base/cursor/cursors_aura.h" #include "grit/ui_resources.h" -#include "ui/base/cursor/cursor.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/point.h" @@ -24,7 +23,15 @@ struct CursorData { HotPoint hot_2x; }; -const CursorData kImageCursors[] = { +struct CursorSet { + const CursorSetType id; + const CursorData* cursors; + const int length; + const CursorData* animated_cursors; + const int animated_length; +}; + +const CursorData kNormalCursors[] = { {ui::kCursorNull, IDR_AURA_CURSOR_PTR, {4, 4}, {8, 9}}, {ui::kCursorPointer, IDR_AURA_CURSOR_PTR, {4, 4}, {8, 9}}, {ui::kCursorNoDrop, IDR_AURA_CURSOR_NO_DROP, {9, 9}, {18, 18}}, @@ -67,11 +74,80 @@ const CursorData kImageCursors[] = { {ui::kCursorGrabbing, IDR_AURA_CURSOR_GRABBING, {9, 9}, {18, 18}}, }; +const CursorData kLargeCursors[] = { + {ui::kCursorNull, IDR_AURA_CURSOR_BIG_PTR, {10, 10}, {10, 10}}, + {ui::kCursorPointer, IDR_AURA_CURSOR_BIG_PTR, {10, 10}, {10, 10}}, + {ui::kCursorNoDrop, IDR_AURA_CURSOR_BIG_NO_DROP, {23, 23}, {23, 23}}, + {ui::kCursorNotAllowed, IDR_AURA_CURSOR_BIG_NO_DROP, {23, 23}, {23, 23}}, + {ui::kCursorCopy, IDR_AURA_CURSOR_BIG_COPY, {23, 23}, {23, 23}}, + {ui::kCursorHand, IDR_AURA_CURSOR_BIG_HAND, {23, 10}, {23, 10}}, + {ui::kCursorMove, IDR_AURA_CURSOR_BIG_MOVE, {28, 28}, {28, 28}}, + {ui::kCursorNorthEastResize, IDR_AURA_CURSOR_BIG_NORTH_EAST_RESIZE, + {31, 28}, {31, 28}}, + {ui::kCursorSouthWestResize, IDR_AURA_CURSOR_BIG_SOUTH_WEST_RESIZE, + {31, 28}, {31, 28}}, + {ui::kCursorSouthEastResize, IDR_AURA_CURSOR_BIG_SOUTH_EAST_RESIZE, + {28, 28}, {28, 28}}, + {ui::kCursorNorthWestResize, IDR_AURA_CURSOR_BIG_NORTH_WEST_RESIZE, + {28, 28}, {28, 28}}, + {ui::kCursorNorthResize, IDR_AURA_CURSOR_BIG_NORTH_RESIZE, + {28, 31}, {28, 31}}, + {ui::kCursorSouthResize, IDR_AURA_CURSOR_BIG_SOUTH_RESIZE, + {28, 31}, {28, 31}}, + {ui::kCursorEastResize, IDR_AURA_CURSOR_BIG_EAST_RESIZE, {31, 28}, {31, 28}}, + {ui::kCursorWestResize, IDR_AURA_CURSOR_BIG_WEST_RESIZE, {31, 28}, {31, 28}}, + {ui::kCursorIBeam, IDR_AURA_CURSOR_BIG_IBEAM, {31, 31}, {31, 31}}, + {ui::kCursorAlias, IDR_AURA_CURSOR_BIG_ALIAS, {51, 15}, {51, 11}}, + {ui::kCursorCell, IDR_AURA_CURSOR_BIG_CELL, {28, 28}, {24, 23}}, + {ui::kCursorContextMenu, IDR_AURA_CURSOR_BIG_CONTEXT_MENU, {4, 4}, {8, 9}}, + {ui::kCursorCross, IDR_AURA_CURSOR_BIG_CROSSHAIR, {31, 31}, {31, 31}}, + {ui::kCursorHelp, IDR_AURA_CURSOR_BIG_HELP, {10, 10}, {8, 9}}, + {ui::kCursorVerticalText, IDR_AURA_CURSOR_BIG_XTERM_HORIZ, + {31, 28}, {31, 28}}, + {ui::kCursorZoomIn, IDR_AURA_CURSOR_BIG_ZOOM_IN, {26, 26}, {26, 26}}, + {ui::kCursorZoomOut, IDR_AURA_CURSOR_BIG_ZOOM_OUT, {26, 26}, {26, 26}}, + {ui::kCursorRowResize, IDR_AURA_CURSOR_BIG_ROW_RESIZE, {28, 31}, {28, 31}}, + {ui::kCursorColumnResize, IDR_AURA_CURSOR_BIG_COL_RESIZE, {31, 28}, {31, 28}}, + {ui::kCursorEastWestResize, IDR_AURA_CURSOR_BIG_EAST_WEST_RESIZE, + {31, 28}, {31, 28}}, + {ui::kCursorNorthSouthResize, IDR_AURA_CURSOR_BIG_NORTH_SOUTH_RESIZE, + {28, 31}, {28, 31}}, + {ui::kCursorNorthEastSouthWestResize, + IDR_AURA_CURSOR_BIG_NORTH_EAST_SOUTH_WEST_RESIZE, {31, 28}, {31, 28}}, + {ui::kCursorNorthWestSouthEastResize, + IDR_AURA_CURSOR_BIG_NORTH_WEST_SOUTH_EAST_RESIZE, {28, 28}, {28, 28}}, + {ui::kCursorGrab, IDR_AURA_CURSOR_BIG_GRAB, {20, 13}, {20, 13}}, + {ui::kCursorGrabbing, IDR_AURA_CURSOR_BIG_GRABBING, {23, 23}, {23, 23}}, +}; + const CursorData kAnimatedCursors[] = { {ui::kCursorWait, IDR_THROBBER, {7, 7}, {14, 14}}, {ui::kCursorProgress, IDR_THROBBER, {7, 7}, {14, 14}}, }; +const CursorSet kCursorSets[] = { + { + CURSOR_SET_NORMAL, + kNormalCursors, arraysize(kNormalCursors), + kAnimatedCursors, arraysize(kAnimatedCursors) + }, + { + CURSOR_SET_LARGE, + kLargeCursors, arraysize(kLargeCursors), + // TODO(yoshiki): Replace animated cursors with big assets. crbug.com/247254 + kAnimatedCursors, arraysize(kAnimatedCursors) + }, +}; + +const CursorSet* GetCursorSetByType(CursorSetType cursor_set_id) { + for (size_t i = 0; i < arraysize(kCursorSets); ++i) { + if (kCursorSets[i].id == cursor_set_id) + return &kCursorSets[i]; + } + + return NULL; +} + bool SearchTable(const CursorData* table, size_t table_length, int id, @@ -96,19 +172,45 @@ bool SearchTable(const CursorData* table, } // namespace -bool GetCursorDataFor(int id, +bool GetCursorDataFor(CursorSetType cursor_set_id, + int id, float scale_factor, int* resource_id, gfx::Point* point) { - return SearchTable(kImageCursors, arraysize(kImageCursors), + const CursorSet* cursor_set = GetCursorSetByType(cursor_set_id); + if (cursor_set && + SearchTable(cursor_set->cursors, + cursor_set->length, + id, scale_factor, resource_id, point)) { + return true; + } + + // Falls back to the default cursor set. + cursor_set = GetCursorSetByType(ui::CURSOR_SET_NORMAL); + DCHECK(cursor_set); + return SearchTable(cursor_set->cursors, + cursor_set->length, id, scale_factor, resource_id, point); } -bool GetAnimatedCursorDataFor(int id, +bool GetAnimatedCursorDataFor(CursorSetType cursor_set_id, + int id, float scale_factor, int* resource_id, gfx::Point* point) { - return SearchTable(kAnimatedCursors, arraysize(kAnimatedCursors), + const CursorSet* cursor_set = GetCursorSetByType(cursor_set_id); + if (cursor_set && + SearchTable(cursor_set->animated_cursors, + cursor_set->animated_length, + id, scale_factor, resource_id, point)) { + return true; + } + + // Falls back to the default cursor set. + cursor_set = GetCursorSetByType(ui::CURSOR_SET_NORMAL); + DCHECK(cursor_set); + return SearchTable(cursor_set->animated_cursors, + cursor_set->animated_length, id, scale_factor, resource_id, point); } diff --git a/chromium/ui/base/cursor/cursors_aura.h b/chromium/ui/base/cursor/cursors_aura.h index 4565a704e76..e916c28575e 100644 --- a/chromium/ui/base/cursor/cursors_aura.h +++ b/chromium/ui/base/cursor/cursors_aura.h @@ -5,6 +5,7 @@ #ifndef UI_BASE_CURSOR_CURSORS_AURA_H_ #define UI_BASE_CURSOR_CURSORS_AURA_H_ +#include "ui/base/cursor/cursor.h" #include "ui/base/ui_export.h" namespace gfx { @@ -19,13 +20,15 @@ const int kAnimatedCursorFrameDelayMs = 25; // ui::kCursorHelp. The IDR will be placed in |resource_id| and the hotspots // for the different DPIs will be placed in |hot_1x| and |hot_2x|. Returns // false if |id| is invalid. -bool UI_EXPORT GetCursorDataFor(int id, +bool UI_EXPORT GetCursorDataFor(CursorSetType cursor_set_id, + int id, float scale_factor, int* resource_id, gfx::Point* point); // Like above, but for animated cursors. -bool UI_EXPORT GetAnimatedCursorDataFor(int id, +bool UI_EXPORT GetAnimatedCursorDataFor(CursorSetType cursor_set_id, + int id, float scale_factor, int* resource_id, gfx::Point* point); diff --git a/chromium/ui/base/default_theme_provider.cc b/chromium/ui/base/default_theme_provider.cc index e60c90029ce..9777b390729 100644 --- a/chromium/ui/base/default_theme_provider.cc +++ b/chromium/ui/base/default_theme_provider.cc @@ -26,8 +26,8 @@ SkColor DefaultThemeProvider::GetColor(int id) const { return 0xff0000ff; } -bool DefaultThemeProvider::GetDisplayProperty(int id, int* result) const { - return false; +int DefaultThemeProvider::GetDisplayProperty(int id) const { + return -1; } bool DefaultThemeProvider::ShouldUseNativeFrame() const { diff --git a/chromium/ui/base/default_theme_provider.h b/chromium/ui/base/default_theme_provider.h index 2594dfbf66a..15fa4a9f487 100644 --- a/chromium/ui/base/default_theme_provider.h +++ b/chromium/ui/base/default_theme_provider.h @@ -26,7 +26,7 @@ class UI_EXPORT DefaultThemeProvider : public ThemeProvider { // Overridden from ui::ThemeProvider: virtual gfx::ImageSkia* GetImageSkiaNamed(int id) const OVERRIDE; virtual SkColor GetColor(int id) const OVERRIDE; - virtual bool GetDisplayProperty(int id, int* result) const OVERRIDE; + virtual int GetDisplayProperty(int id) const OVERRIDE; virtual bool ShouldUseNativeFrame() const OVERRIDE; virtual bool HasCustomImage(int id) const OVERRIDE; virtual base::RefCountedMemory* GetRawData( diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc b/chromium/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc index 52aa7c6dce2..ffd0a3c4b04 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc @@ -6,7 +6,7 @@ #include "base/logging.h" #include "base/memory/ref_counted_memory.h" -#include "base/message_loop/message_pump_aurax11.h" +#include "base/message_loop/message_pump_x11.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "net/base/net_util.h" @@ -42,7 +42,7 @@ const char* kAtomsToCache[] = { OSExchangeDataProviderAuraX11::OSExchangeDataProviderAuraX11( ::Window x_window, const SelectionFormatMap& selection) - : x_display_(GetXDisplay()), + : x_display_(gfx::GetXDisplay()), x_root_window_(DefaultRootWindow(x_display_)), own_window_(false), x_window_(x_window), @@ -55,7 +55,7 @@ OSExchangeDataProviderAuraX11::OSExchangeDataProviderAuraX11( } OSExchangeDataProviderAuraX11::OSExchangeDataProviderAuraX11() - : x_display_(GetXDisplay()), + : x_display_(gfx::GetXDisplay()), x_root_window_(DefaultRootWindow(x_display_)), own_window_(true), x_window_(XCreateWindow( @@ -77,12 +77,12 @@ OSExchangeDataProviderAuraX11::OSExchangeDataProviderAuraX11() XStoreName(x_display_, x_window_, "Chromium Drag & Drop Window"); - base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, x_window_); + base::MessagePumpX11::Current()->AddDispatcherForWindow(this, x_window_); } OSExchangeDataProviderAuraX11::~OSExchangeDataProviderAuraX11() { if (own_window_) { - base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(x_window_); + base::MessagePumpX11::Current()->RemoveDispatcherForWindow(x_window_); XDestroyWindow(x_display_, x_window_); } } @@ -196,13 +196,14 @@ bool OSExchangeDataProviderAuraX11::GetURLAndTitle( std::vector<base::string16> tokens; size_t num_tokens = Tokenize(unparsed, ASCIIToUTF16("\n"), &tokens); - if (num_tokens >= 2) { + if (num_tokens > 0) { + if (num_tokens > 1) + *title = tokens[1]; + else + *title = string16(); + *url = GURL(tokens[0]); - *title = tokens[1]; return true; - } else { - NOTREACHED() << "Data that claimed to be a Mozilla URL has " - << num_tokens << " tokens instead of 2."; } } else if (data.GetType() == atom_cache_.GetAtom( Clipboard::kMimeTypeURIList)) { diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_aurax11_unittest.cc b/chromium/ui/base/dragdrop/os_exchange_data_provider_aurax11_unittest.cc new file mode 100644 index 00000000000..c3a944aa9e5 --- /dev/null +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_aurax11_unittest.cc @@ -0,0 +1,43 @@ +// 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 "ui/base/dragdrop/os_exchange_data_provider_aurax11.h" + +// Clean up X11 header polution +#undef None +#undef Bool + +#include "base/message_loop/message_loop.h" +#include "base/strings/string16.h" +#include "base/strings/utf_string_conversions.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +const char kGoogleTitle[] = "Google"; +const char kGoogleURL[] = "http://www.google.com/"; + +TEST(OSExchangeDataProviderAuraX11Test, MozillaURL) { + base::MessageLoopForUI message_loop; + ui::OSExchangeDataProviderAuraX11 provider; + + // Check that we can get titled entries. + provider.SetURL(GURL(kGoogleURL), ASCIIToUTF16(kGoogleTitle)); + { + GURL out_gurl; + base::string16 out_str; + EXPECT_TRUE(provider.GetURLAndTitle(&out_gurl, &out_str)); + EXPECT_EQ(ASCIIToUTF16(kGoogleTitle), out_str); + EXPECT_EQ(kGoogleURL, out_gurl.spec()); + } + + // Check that we can get non-titled entries. + provider.SetURL(GURL(kGoogleURL), string16()); + { + GURL out_gurl; + base::string16 out_str; + EXPECT_TRUE(provider.GetURLAndTitle(&out_gurl, &out_str)); + EXPECT_EQ(string16(), out_str); + EXPECT_EQ(kGoogleURL, out_gurl.spec()); + } +} diff --git a/chromium/ui/base/events/event_conversion_gtk.cc b/chromium/ui/base/events/event_conversion_gtk.cc deleted file mode 100644 index bc15dac260b..00000000000 --- a/chromium/ui/base/events/event_conversion_gtk.cc +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2012 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 "ui/base/events/event_conversion_gtk.h" - -#include "ui/base/events/event_constants.h" - -namespace ui { - -int GdkModifierToEventFlag(GdkModifierType gdk_modifier) { - int event_flags = 0; - if (gdk_modifier & GDK_SHIFT_MASK) - event_flags |= EF_SHIFT_DOWN; - if (gdk_modifier & GDK_CONTROL_MASK) - event_flags |= EF_CONTROL_DOWN; - if (gdk_modifier & GDK_MOD1_MASK) - event_flags |= EF_ALT_DOWN; - return event_flags; -} - -GdkModifierType EventFlagToGdkModifier(int event_flag) { - int modifier = 0; - if (event_flag & EF_SHIFT_DOWN) - modifier |= GDK_SHIFT_MASK; - if (event_flag & EF_CONTROL_DOWN) - modifier |= GDK_CONTROL_MASK; - if (event_flag & EF_ALT_DOWN) - modifier |= GDK_MOD1_MASK; - return static_cast<GdkModifierType>(modifier); -} - -} // namespace ui diff --git a/chromium/ui/base/events/event_conversion_gtk.h b/chromium/ui/base/events/event_conversion_gtk.h deleted file mode 100644 index a78d09230af..00000000000 --- a/chromium/ui/base/events/event_conversion_gtk.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef UI_BASE_EVENTS_EVENT_CONVERSION_GTK_H_ -#define UI_BASE_EVENTS_EVENT_CONVERSION_GTK_H_ - -#include <gtk/gtk.h> - -#include "ui/base/ui_export.h" - -namespace ui { - -UI_EXPORT int GdkModifierToEventFlag(GdkModifierType gdk_modifier); - -UI_EXPORT GdkModifierType EventFlagToGdkModifier(int event_flag); - -} // namespace ui - -#endif // UI_BASE_EVENTS_EVENT_CONVERSION_GTK_H_ diff --git a/chromium/ui/base/gestures/gesture_configuration.cc b/chromium/ui/base/gestures/gesture_configuration.cc index 89d09b0954f..1d1cb73c37a 100644 --- a/chromium/ui/base/gestures/gesture_configuration.cc +++ b/chromium/ui/base/gestures/gesture_configuration.cc @@ -21,14 +21,14 @@ double double GestureConfiguration::max_swipe_deviation_ratio_ = 3; double GestureConfiguration::max_touch_down_duration_in_seconds_for_click_ = 0.8; -double GestureConfiguration::max_touch_move_in_pixels_for_click_ = 10; +double GestureConfiguration::max_touch_move_in_pixels_for_click_ = 25; double GestureConfiguration::max_distance_between_taps_for_double_tap_ = 20; double GestureConfiguration::min_distance_for_pinch_scroll_in_pixels_ = 20; double GestureConfiguration::min_flick_speed_squared_ = 550.f * 550.f; double GestureConfiguration::min_pinch_update_distance_in_pixels_ = 5; double GestureConfiguration::min_rail_break_velocity_ = 200; double GestureConfiguration::min_scroll_delta_squared_ = 4 * 4; -int GestureConfiguration::min_scroll_successive_velocity_events_ = 3; +int GestureConfiguration::min_scroll_successive_velocity_events_ = 4; float GestureConfiguration::min_scroll_velocity_ = 30.0f; double GestureConfiguration::min_swipe_speed_ = 20; double GestureConfiguration::scroll_prediction_seconds_ = 0.03; diff --git a/chromium/ui/base/gestures/gesture_configuration.h b/chromium/ui/base/gestures/gesture_configuration.h index 68d2573d5b2..3b4df56fdf4 100644 --- a/chromium/ui/base/gestures/gesture_configuration.h +++ b/chromium/ui/base/gestures/gesture_configuration.h @@ -232,7 +232,6 @@ class UI_EXPORT GestureConfiguration { static double min_pinch_update_distance_in_pixels_; static double min_rail_break_velocity_; static double min_scroll_delta_squared_; - // TODO(rjkroege): Expose these in chrome://gesture static int min_scroll_successive_velocity_events_; static float min_scroll_velocity_; static double min_swipe_speed_; diff --git a/chromium/ui/base/gestures/gesture_point.cc b/chromium/ui/base/gestures/gesture_point.cc index 105779b17c2..2233bf11dc1 100644 --- a/chromium/ui/base/gestures/gesture_point.cc +++ b/chromium/ui/base/gestures/gesture_point.cc @@ -7,11 +7,11 @@ #include <cmath> #include "base/basictypes.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_constants.h" #include "ui/base/gestures/gesture_configuration.h" #include "ui/base/gestures/gesture_types.h" #include "ui/base/gestures/gesture_util.h" +#include "ui/events/event.h" +#include "ui/events/event_constants.h" namespace ui { @@ -107,6 +107,8 @@ bool GesturePoint::IsInTripleClickWindow(const TouchEvent& event) const { } bool GesturePoint::IsInScrollWindow(const TouchEvent& event) const { + if (IsConsistentScrollingActionUnderway()) + return true; return event.type() == ui::ET_TOUCH_MOVED && !IsInsideManhattanSquare(event); } @@ -130,7 +132,7 @@ bool GesturePoint::DidScroll(const TouchEvent& event, int dist) const { return abs(d.x()) > dist || abs(d.y()) > dist; } -bool GesturePoint::IsConsistentScrollingActionUnderway() { +bool GesturePoint::IsConsistentScrollingActionUnderway() const { int me = GestureConfiguration::min_scroll_successive_velocity_events(); if (abs(same_direction_count_.x()) >= me || abs(same_direction_count_.y()) >= me) diff --git a/chromium/ui/base/gestures/gesture_point.h b/chromium/ui/base/gestures/gesture_point.h index b84c3bd7a3f..60dad3207fb 100644 --- a/chromium/ui/base/gestures/gesture_point.h +++ b/chromium/ui/base/gestures/gesture_point.h @@ -40,11 +40,11 @@ class GesturePoint { bool IsInClickWindow(const TouchEvent& event) const; bool IsInDoubleClickWindow(const TouchEvent& event) const; bool IsInTripleClickWindow(const TouchEvent& event) const; - bool IsInScrollWindow(const TouchEvent& event) const; bool IsInFlickWindow(const TouchEvent& event); bool IsInHorizontalRailWindow() const; bool IsInVerticalRailWindow() const; bool IsInsideManhattanSquare(const TouchEvent& event) const; + bool IsInScrollWindow(const TouchEvent& event) const; bool BreaksHorizontalRail(); bool BreaksVerticalRail(); bool DidScroll(const TouchEvent& event, int distance) const; @@ -79,12 +79,12 @@ class GesturePoint { const gfx::Rect& enclosing_rectangle() const { return enclosing_rect_; } - // Tests if the point has a consistent scroll vector across a window of touch - // move events. - bool IsConsistentScrollingActionUnderway(); - private: // Various statistical functions to manipulate gestures. + + // Tests if the point has a consistent scroll vector across a window of touch + // move events. + bool IsConsistentScrollingActionUnderway() const; bool IsInClickTimeWindow() const; bool IsInClickAggregateTimeWindow(double before, double after) const; bool IsPointInsideManhattanSquare(gfx::Point p1, gfx::Point p2) const; diff --git a/chromium/ui/base/gestures/gesture_recognizer.h b/chromium/ui/base/gestures/gesture_recognizer.h index b32bade8289..dbb139bc7d8 100644 --- a/chromium/ui/base/gestures/gesture_recognizer.h +++ b/chromium/ui/base/gestures/gesture_recognizer.h @@ -8,9 +8,9 @@ #include <vector> #include "base/memory/scoped_vector.h" -#include "ui/base/events/event_constants.h" #include "ui/base/gestures/gesture_types.h" #include "ui/base/ui_export.h" +#include "ui/events/event_constants.h" namespace ui { // A GestureRecognizer is an abstract base class for conversion of touch events @@ -25,7 +25,7 @@ class UI_EXPORT GestureRecognizer { virtual ~GestureRecognizer() {} // Invoked for each touch event that could contribute to the current gesture. - // Returns list of zero or more GestureEvents identified after processing + // Returns list of zero or more GestureEvents identified after processing // TouchEvent. // Caller would be responsible for freeing up Gestures. virtual Gestures* ProcessTouchEventForGesture(const TouchEvent& event, diff --git a/chromium/ui/base/gestures/gesture_recognizer_impl.cc b/chromium/ui/base/gestures/gesture_recognizer_impl.cc index 0e315a16cca..51aaa3033bd 100644 --- a/chromium/ui/base/gestures/gesture_recognizer_impl.cc +++ b/chromium/ui/base/gestures/gesture_recognizer_impl.cc @@ -7,12 +7,12 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/time/time.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/events/event_utils.h" #include "ui/base/gestures/gesture_configuration.h" #include "ui/base/gestures/gesture_sequence.h" #include "ui/base/gestures/gesture_types.h" +#include "ui/events/event.h" +#include "ui/events/event_constants.h" +#include "ui/events/event_utils.h" namespace ui { diff --git a/chromium/ui/base/gestures/gesture_recognizer_impl.h b/chromium/ui/base/gestures/gesture_recognizer_impl.h index 812bc057578..5f9caf25c02 100644 --- a/chromium/ui/base/gestures/gesture_recognizer_impl.h +++ b/chromium/ui/base/gestures/gesture_recognizer_impl.h @@ -10,9 +10,9 @@ #include "base/memory/linked_ptr.h" #include "base/memory/scoped_ptr.h" -#include "ui/base/events/event_constants.h" #include "ui/base/gestures/gesture_recognizer.h" #include "ui/base/ui_export.h" +#include "ui/events/event_constants.h" #include "ui/gfx/point.h" namespace ui { diff --git a/chromium/ui/base/gestures/gesture_sequence.cc b/chromium/ui/base/gestures/gesture_sequence.cc index b4f32e4b50d..5d3619daa0b 100644 --- a/chromium/ui/base/gestures/gesture_sequence.cc +++ b/chromium/ui/base/gestures/gesture_sequence.cc @@ -12,11 +12,11 @@ #include "base/memory/scoped_ptr.h" #include "base/strings/string_number_conversions.h" #include "base/time/time.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_constants.h" #include "ui/base/gestures/gesture_configuration.h" #include "ui/base/gestures/gesture_util.h" #include "ui/base/ui_base_switches.h" +#include "ui/events/event.h" +#include "ui/events/event_constants.h" #include "ui/gfx/rect.h" namespace ui { @@ -108,6 +108,27 @@ enum EdgeStateSignatureType { GST_PENDING_SYNTHETIC_CLICK_SECOND_PRESSED = G(GS_PENDING_SYNTHETIC_CLICK, 1, TS_PRESSED, TSI_NOT_PROCESSED), + GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_RELEASED = + G(GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL, + 0, + TS_RELEASED, + TSI_NOT_PROCESSED), + + GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_RELEASED_HANDLED = + G(GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL, 0, TS_RELEASED, TSI_PROCESSED), + + GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_MOVED = + G(GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL, 0, TS_MOVED, TSI_ALWAYS), + + GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_STATIONARY = + G(GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL, 0, TS_STATIONARY, TSI_ALWAYS), + + GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_CANCELLED = + G(GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL, 0, TS_CANCELLED, TSI_ALWAYS), + + GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_SECOND_PRESSED = + G(GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL, 1, TS_PRESSED, TSI_NOT_PROCESSED), + GST_SCROLL_FIRST_RELEASED = G(GS_SCROLL, 0, TS_RELEASED, TSI_ALWAYS), @@ -243,6 +264,12 @@ EdgeStateSignatureType Signature(GestureState gesture_state, case GST_PENDING_SYNTHETIC_CLICK_FIRST_STATIONARY: case GST_PENDING_SYNTHETIC_CLICK_FIRST_CANCELLED: case GST_PENDING_SYNTHETIC_CLICK_SECOND_PRESSED: + case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_RELEASED: + case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_RELEASED_HANDLED: + case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_MOVED: + case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_STATIONARY: + case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_CANCELLED: + case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_SECOND_PRESSED: case GST_SCROLL_FIRST_RELEASED: case GST_SCROLL_FIRST_MOVED: case GST_SCROLL_FIRST_CANCELLED: @@ -419,15 +446,26 @@ GestureSequence::Gestures* GestureSequence::ProcessTouchEventForGesture( point.UpdateForScroll(); } break; + case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_MOVED: + case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_STATIONARY: + // No scrolling allowed, so nothing happens. + break; case GST_PENDING_SYNTHETIC_CLICK_FIRST_MOVED_PROCESSED: - // TODO(rbyers): This should be able to trigger a TapCancel - // if we moved far enough. crbug.com/146397 + if (point.IsInScrollWindow(event)) { + PrependTapCancelGestureEvent(point, gestures.get()); + set_state(GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL); + } break; case GST_PENDING_SYNTHETIC_CLICK_FIRST_RELEASED_HANDLED: case GST_PENDING_SYNTHETIC_CLICK_FIRST_CANCELLED: PrependTapCancelGestureEvent(point, gestures.get()); set_state(GS_NO_GESTURE); break; + case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_RELEASED: + case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_RELEASED_HANDLED: + case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_FIRST_CANCELLED: + set_state(GS_NO_GESTURE); + break; case GST_SCROLL_FIRST_MOVED: if (scroll_type_ == ST_VERTICAL || scroll_type_ == ST_HORIZONTAL) @@ -442,12 +480,11 @@ GestureSequence::Gestures* GestureSequence::ProcessTouchEventForGesture( break; case GST_PENDING_SYNTHETIC_CLICK_SECOND_PRESSED: PrependTapCancelGestureEvent(point, gestures.get()); - if (IsSecondTouchDownCloseEnoughForTwoFingerTap()) { - TwoFingerTouchDown(event, point, gestures.get()); - set_state(GS_PENDING_TWO_FINGER_TAP); - break; - } - // fall through + TwoFingerTapOrPinch(event, point, gestures.get()); + break; + case GST_PENDING_SYNTHETIC_CLICK_NO_SCROLL_SECOND_PRESSED: + TwoFingerTapOrPinch(event, point, gestures.get()); + break; case GST_SCROLL_SECOND_PRESSED: PinchStart(event, point, gestures.get()); set_state(GS_PINCH); @@ -901,8 +938,7 @@ bool GestureSequence::ScrollStart(const TouchEvent& event, GesturePoint& point, Gestures* gestures) { DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK); - if (!point.IsConsistentScrollingActionUnderway() && - !point.IsInScrollWindow(event)) + if (!point.IsInScrollWindow(event)) return false; AppendScrollGestureBegin(point, point.first_touch_position(), gestures); if (point.IsInHorizontalRailWindow()) @@ -953,7 +989,10 @@ bool GestureSequence::TouchDown(const TouchEvent& event, bool GestureSequence::TwoFingerTouchDown(const TouchEvent& event, const GesturePoint& point, Gestures* gestures) { - DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK || state_ == GS_SCROLL); + DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK || + state_ == GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL || + state_ == GS_SCROLL); + if (state_ == GS_SCROLL) { AppendScrollGestureEnd(point, point.last_touch_position(), gestures, 0.f, 0.f); @@ -1171,6 +1210,19 @@ bool GestureSequence::MaybeSwipe(const TouchEvent& event, return true; } +void GestureSequence::TwoFingerTapOrPinch(const TouchEvent& event, + const GesturePoint& point, + Gestures* gestures) { + if (IsSecondTouchDownCloseEnoughForTwoFingerTap()) { + TwoFingerTouchDown(event, point, gestures); + set_state(GS_PENDING_TWO_FINGER_TAP); + } else { + PinchStart(event, point, gestures); + set_state(GS_PINCH); + } +} + + void GestureSequence::StopLongPressTimerIfRequired(const TouchEvent& event) { if (!GetLongPressTimer()->IsRunning() || event.type() != ui::ET_TOUCH_MOVED) diff --git a/chromium/ui/base/gestures/gesture_sequence.h b/chromium/ui/base/gestures/gesture_sequence.h index 9aff570dd93..ddb90834338 100644 --- a/chromium/ui/base/gestures/gesture_sequence.h +++ b/chromium/ui/base/gestures/gesture_sequence.h @@ -6,9 +6,9 @@ #define UI_BASE_GESTURES_GESTURE_SEQUENCE_H_ #include "base/timer/timer.h" -#include "ui/base/events/event_constants.h" #include "ui/base/gestures/gesture_point.h" #include "ui/base/gestures/gesture_recognizer.h" +#include "ui/events/event_constants.h" #include "ui/gfx/rect.h" namespace ui { @@ -19,6 +19,7 @@ class GestureEvent; enum GestureState { GS_NO_GESTURE, GS_PENDING_SYNTHETIC_CLICK, + GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL, GS_SCROLL, GS_PINCH, GS_PENDING_TWO_FINGER_TAP, @@ -171,6 +172,10 @@ class UI_EXPORT GestureSequence { const GesturePoint& point, Gestures* gestures); + void TwoFingerTapOrPinch(const TouchEvent& event, + const GesturePoint& point, + Gestures* gestures); + void StopLongPressTimerIfRequired(const TouchEvent& event); // Current state of gesture recognizer. diff --git a/chromium/ui/base/gestures/gesture_types.h b/chromium/ui/base/gestures/gesture_types.h index 584ea171338..bea1553fe38 100644 --- a/chromium/ui/base/gestures/gesture_types.h +++ b/chromium/ui/base/gestures/gesture_types.h @@ -6,7 +6,7 @@ #define UI_BASE_GESTURES_GESTURE_TYPES_H_ #include "base/logging.h" -#include "ui/base/events/event_constants.h" +#include "ui/events/event_constants.h" #include "ui/gfx/rect.h" namespace ui { diff --git a/chromium/ui/base/gestures/gestures.dot b/chromium/ui/base/gestures/gestures.dot index 868c5421eb6..8524930d8db 100644 --- a/chromium/ui/base/gestures/gestures.dot +++ b/chromium/ui/base/gestures/gestures.dot @@ -1,6 +1,6 @@ // A diagram of the state machine found in gesture_sequence.cc // To generate a pdf: -// dot -Tpdf -ooutput.pdf gestures.dot +// dot -Tpdf -ooutput.pdf gestures.dot // // If you alter this diagram, please update: // sites.google.com/a/chromium.org/dev/developers/design-documents/aura/gesture-recognizer @@ -17,25 +17,31 @@ R : Release \l\ M_Delay : Move after a certain delay}" shape = record] -subgraph none_pending { GS_NO_GESTURE -> GS_PENDING_SYNTHETIC_CLICK [label= "D0"]; + GS_PENDING_SYNTHETIC_CLICK -> GS_SCROLL [label= "M0\n S0"]; GS_PENDING_SYNTHETIC_CLICK -> GS_PENDING_SYNTHETIC_CLICK [label= "M0\n S0"]; GS_PENDING_SYNTHETIC_CLICK -> GS_NO_GESTURE [label= "C0\n R0"]; -} +GS_PENDING_SYNTHETIC_CLICK -> GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL [label= "M0"]; +GS_PENDING_SYNTHETIC_CLICK -> GS_PENDING_TWO_FINGER_TAP [label= "D1"]; + +GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL -> GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL [label= "M0\n S0"]; +GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL -> GS_NO_GESTURE [label= "C0\n R0"]; +GS_PENDING_SYNTHETIC_CLICK_NO_SCROLL -> GS_PENDING_TWO_FINGER_TAP [label= "D1"]; GS_SCROLL -> GS_SCROLL [label= "M0"]; GS_SCROLL -> GS_NO_GESTURE [label= "C0\n R0\n"]; -GS_PENDING_SYNTHETIC_CLICK -> GS_PENDING_TWO_FINGER_TAP [label= "D1"]; GS_SCROLL -> GS_PENDING_TWO_FINGER_TAP [label= "D1"]; + GS_PENDING_TWO_FINGER_TAP -> GS_PINCH [label= "M0\n M1"]; GS_PENDING_TWO_FINGER_TAP -> GS_PINCH [label= "M_Delay0\n M_Delay1"]; GS_PENDING_TWO_FINGER_TAP -> GS_PINCH [label= "D2"]; GS_PENDING_TWO_FINGER_TAP -> GS_SCROLL [label= "R0\n R1\n C0\n C1"]; + GS_PINCH -> GS_PINCH [label= "M0\n M1"]; GS_PINCH -> GS_SCROLL [label= "C0\n R0\n C1\n R1"]; - GS_PINCH -> GS_PENDING_THREE_FINGER_SWIPE [label= "D2"]; + GS_PENDING_THREE_FINGER_SWIPE -> GS_PINCH [label= "C0\n R0\n C1\n R1\n C2\n R2"]; GS_PENDING_THREE_FINGER_SWIPE -> GS_PENDING_THREE_FINGER_SWIPE [label= "M0\n M1\n M2"]; -} +}
\ No newline at end of file diff --git a/chromium/ui/base/gtk/event_synthesis_gtk.cc b/chromium/ui/base/gtk/event_synthesis_gtk.cc index bd3cb8aa220..ea56162dd22 100644 --- a/chromium/ui/base/gtk/event_synthesis_gtk.cc +++ b/chromium/ui/base/gtk/event_synthesis_gtk.cc @@ -4,7 +4,7 @@ #include "ui/base/gtk/event_synthesis_gtk.h" -#include "ui/base/keycodes/keyboard_code_conversion_gtk.h" +#include "ui/events/keycodes/keyboard_code_conversion_gtk.h" namespace ui { diff --git a/chromium/ui/base/gtk/event_synthesis_gtk.h b/chromium/ui/base/gtk/event_synthesis_gtk.h index 50dde0f08c5..1839e29949a 100644 --- a/chromium/ui/base/gtk/event_synthesis_gtk.h +++ b/chromium/ui/base/gtk/event_synthesis_gtk.h @@ -13,8 +13,8 @@ #include <gdk/gdkkeysyms.h> #include <vector> -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/base/ui_export.h" +#include "ui/events/keycodes/keyboard_codes.h" namespace ui { diff --git a/chromium/ui/base/gtk/gtk_expanded_container.cc b/chromium/ui/base/gtk/gtk_expanded_container.cc index 30fc3db58b6..6b39821d806 100644 --- a/chromium/ui/base/gtk/gtk_expanded_container.cc +++ b/chromium/ui/base/gtk/gtk_expanded_container.cc @@ -8,7 +8,7 @@ #include <algorithm> -#include "ui/base/gtk/gtk_compat.h" +#include "ui/gfx/gtk_compat.h" namespace { diff --git a/chromium/ui/base/gtk/gtk_floating_container.cc b/chromium/ui/base/gtk/gtk_floating_container.cc index 929216eab22..dd1ac26b0a2 100644 --- a/chromium/ui/base/gtk/gtk_floating_container.cc +++ b/chromium/ui/base/gtk/gtk_floating_container.cc @@ -8,7 +8,7 @@ #include <algorithm> -#include "ui/base/gtk/gtk_compat.h" +#include "ui/gfx/gtk_compat.h" namespace { diff --git a/chromium/ui/base/gtk/gtk_im_context_util.cc b/chromium/ui/base/gtk/gtk_im_context_util.cc index b60856bf3f1..dfd5f3f9e8d 100644 --- a/chromium/ui/base/gtk/gtk_im_context_util.cc +++ b/chromium/ui/base/gtk/gtk_im_context_util.cc @@ -40,7 +40,7 @@ void ExtractCompositionTextFromGtkPreedit(const gchar* utf8_text, size_t cursor_offset = char16_offsets[std::max(0, std::min(char_length, cursor_position))]; - composition->selection = ui::Range(cursor_offset); + composition->selection = gfx::Range(cursor_offset); if (attrs) { int utf8_length = strlen(utf8_text); diff --git a/chromium/ui/base/gtk/gtk_windowing.cc b/chromium/ui/base/gtk/gtk_windowing.cc index 4ca4a1d2786..e378c8463ad 100644 --- a/chromium/ui/base/gtk/gtk_windowing.cc +++ b/chromium/ui/base/gtk/gtk_windowing.cc @@ -7,8 +7,8 @@ #include <gdk/gdkx.h> #include "base/logging.h" -#include "ui/base/gtk/gtk_compat.h" #include "ui/base/x/x11_util.h" +#include "ui/gfx/gtk_compat.h" namespace ui { diff --git a/chromium/ui/base/ime/character_composer.cc b/chromium/ui/base/ime/character_composer.cc index 0402be2ba97..6fff429a2ac 100644 --- a/chromium/ui/base/ime/character_composer.cc +++ b/chromium/ui/base/ime/character_composer.cc @@ -14,9 +14,9 @@ // Note for Gtk removal: gdkkeysyms.h only contains a set of // '#define GDK_KeyName 0xNNNN' macros and does not #include any Gtk headers. #include "third_party/gtk+/gdk/gdkkeysyms.h" -#include "ui/base/events/event_constants.h" #include "ui/base/glib/glib_integers.h" -#include "ui/base/x/x11_util.h" +#include "ui/events/event_constants.h" +#include "ui/gfx/x/x11_types.h" // Note for Gtk removal: gtkimcontextsimpleseqs.h does not #include any Gtk // headers and only contains one big guint16 array |gtk_compose_seqs_compact| @@ -371,7 +371,7 @@ bool UTF32CharacterToUTF16(uint32 character, string16* output) { // Converts a X keycode to a X keysym with no modifiers. KeySym XKeyCodeToXKeySym(unsigned int keycode) { - Display* display = ui::GetXDisplay(); + XDisplay* display = gfx::GetXDisplay(); if (!display) return NoSymbol; diff --git a/chromium/ui/base/ime/character_composer_unittest.cc b/chromium/ui/base/ime/character_composer_unittest.cc index 9a7921931a9..0710204997e 100644 --- a/chromium/ui/base/ime/character_composer_unittest.cc +++ b/chromium/ui/base/ime/character_composer_unittest.cc @@ -7,8 +7,8 @@ #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/gtk+/gdk/gdkkeysyms.h" -#include "ui/base/events/event_constants.h" #include "ui/base/glib/glib_integers.h" +#include "ui/events/event_constants.h" namespace ui { diff --git a/chromium/ui/base/ime/composition_text.cc b/chromium/ui/base/ime/composition_text.cc index 660b3ef7ca4..f85bc748758 100644 --- a/chromium/ui/base/ime/composition_text.cc +++ b/chromium/ui/base/ime/composition_text.cc @@ -15,7 +15,7 @@ CompositionText::~CompositionText() { void CompositionText::Clear() { text.clear(); underlines.clear(); - selection = Range(); + selection = gfx::Range(); } } // namespace ui diff --git a/chromium/ui/base/ime/composition_text.h b/chromium/ui/base/ime/composition_text.h index b97712a6322..5beaffc0eb7 100644 --- a/chromium/ui/base/ime/composition_text.h +++ b/chromium/ui/base/ime/composition_text.h @@ -7,8 +7,8 @@ #include "base/strings/string16.h" #include "ui/base/ime/composition_underline.h" -#include "ui/base/range/range.h" #include "ui/base/ui_export.h" +#include "ui/gfx/range/range.h" namespace ui { @@ -47,7 +47,7 @@ struct UI_EXPORT CompositionText { // if the range length is zero. Usually it's used for representing the target // clause (on Windows). Gtk doesn't have such concept, so background color is // usually used instead. - Range selection; + gfx::Range selection; }; } // namespace ui diff --git a/chromium/ui/base/ime/dummy_input_method.cc b/chromium/ui/base/ime/dummy_input_method.cc index f762e3b0b94..2fc206dee5d 100644 --- a/chromium/ui/base/ime/dummy_input_method.cc +++ b/chromium/ui/base/ime/dummy_input_method.cc @@ -32,6 +32,13 @@ bool DummyInputMethod::OnUntranslatedIMEMessage(const base::NativeEvent& event, void DummyInputMethod::SetFocusedTextInputClient(TextInputClient* client) { } +void DummyInputMethod::SetStickyFocusedTextInputClient( + TextInputClient* client) { +} + +void DummyInputMethod::DetachTextInputClient(TextInputClient* client) { +} + TextInputClient* DummyInputMethod::GetTextInputClient() const { return NULL; } @@ -72,6 +79,10 @@ TextInputType DummyInputMethod::GetTextInputType() const { return TEXT_INPUT_TYPE_NONE; } +TextInputMode DummyInputMethod::GetTextInputMode() const { + return TEXT_INPUT_MODE_DEFAULT; +} + bool DummyInputMethod::CanComposeInline() const { return true; } diff --git a/chromium/ui/base/ime/dummy_input_method.h b/chromium/ui/base/ime/dummy_input_method.h index 2276ae5d9a6..edceb0eac8e 100644 --- a/chromium/ui/base/ime/dummy_input_method.h +++ b/chromium/ui/base/ime/dummy_input_method.h @@ -25,6 +25,9 @@ class DummyInputMethod : public InputMethod { virtual bool OnUntranslatedIMEMessage( const base::NativeEvent& event, NativeEventResult* result) OVERRIDE; virtual void SetFocusedTextInputClient(TextInputClient* client) OVERRIDE; + virtual void SetStickyFocusedTextInputClient( + TextInputClient* client) OVERRIDE; + virtual void DetachTextInputClient(TextInputClient* client) OVERRIDE; virtual TextInputClient* GetTextInputClient() const OVERRIDE; virtual bool DispatchKeyEvent(const base::NativeEvent& event) OVERRIDE; virtual bool DispatchFabricatedKeyEvent(const ui::KeyEvent& event) OVERRIDE; @@ -36,6 +39,7 @@ class DummyInputMethod : public InputMethod { virtual base::i18n::TextDirection GetInputTextDirection() OVERRIDE; virtual bool IsActive() OVERRIDE; virtual TextInputType GetTextInputType() const OVERRIDE; + virtual TextInputMode GetTextInputMode() const OVERRIDE; virtual bool CanComposeInline() const OVERRIDE; virtual bool IsCandidatePopupOpen() const OVERRIDE; virtual void AddObserver(InputMethodObserver* observer) OVERRIDE; diff --git a/chromium/ui/base/ime/dummy_input_method_delegate.cc b/chromium/ui/base/ime/dummy_input_method_delegate.cc new file mode 100644 index 00000000000..e7bb7dae2bd --- /dev/null +++ b/chromium/ui/base/ime/dummy_input_method_delegate.cc @@ -0,0 +1,26 @@ +// 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 "ui/base/ime/dummy_input_method_delegate.h" + +namespace ui { +namespace internal { + +DummyInputMethodDelegate::DummyInputMethodDelegate() {} +DummyInputMethodDelegate::~DummyInputMethodDelegate() {} + +bool DummyInputMethodDelegate::DispatchKeyEventPostIME( + const base::NativeEvent& native_key_event) { + return true; +} + +bool DummyInputMethodDelegate::DispatchFabricatedKeyEventPostIME( + ui::EventType type, + ui::KeyboardCode key_code, + int flags) { + return true; +} + +} // namespace internal +} // namespace ui diff --git a/chromium/ui/base/ime/dummy_input_method_delegate.h b/chromium/ui/base/ime/dummy_input_method_delegate.h new file mode 100644 index 00000000000..360d0b42b38 --- /dev/null +++ b/chromium/ui/base/ime/dummy_input_method_delegate.h @@ -0,0 +1,36 @@ +// 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. + +#ifndef UI_BASE_IME_DUMMY_INPUT_METHOD_DELEGATE_H_ +#define UI_BASE_IME_DUMMY_INPUT_METHOD_DELEGATE_H_ + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "ui/base/ime/input_method_delegate.h" +#include "ui/base/ui_export.h" + +namespace ui { +namespace internal { + +class UI_EXPORT DummyInputMethodDelegate + : NON_EXPORTED_BASE(public InputMethodDelegate) { + public: + DummyInputMethodDelegate(); + virtual ~DummyInputMethodDelegate(); + + // InputMethodDelegate overrides: + virtual bool DispatchKeyEventPostIME( + const base::NativeEvent& native_key_event) OVERRIDE; + virtual bool DispatchFabricatedKeyEventPostIME(ui::EventType type, + ui::KeyboardCode key_code, + int flags) OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(DummyInputMethodDelegate); +}; + +} // namespace internal +} // namespace ui + +#endif // UI_BASE_IME_DUMMY_INPUT_METHOD_DELEGATE_H_ diff --git a/chromium/ui/base/ime/dummy_text_input_client.cc b/chromium/ui/base/ime/dummy_text_input_client.cc new file mode 100644 index 00000000000..c12daef897a --- /dev/null +++ b/chromium/ui/base/ime/dummy_text_input_client.cc @@ -0,0 +1,101 @@ +// 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 "ui/base/ime/dummy_text_input_client.h" +#include "ui/gfx/rect.h" + +namespace ui { + +DummyTextInputClient::DummyTextInputClient() { +} + +DummyTextInputClient::~DummyTextInputClient() { +} + +void DummyTextInputClient::SetCompositionText( + const ui::CompositionText& composition) { +} + +void DummyTextInputClient::ConfirmCompositionText() { +} + +void DummyTextInputClient::ClearCompositionText() { +} + +void DummyTextInputClient::InsertText(const string16& text) { +} + +void DummyTextInputClient::InsertChar(char16 ch, int flags) { +} + +gfx::NativeWindow DummyTextInputClient::GetAttachedWindow() const { + return NULL; +} + +ui::TextInputType DummyTextInputClient::GetTextInputType() const { + return TEXT_INPUT_TYPE_NONE; +} + +ui::TextInputMode DummyTextInputClient::GetTextInputMode() const { + return TEXT_INPUT_MODE_DEFAULT; +} + +bool DummyTextInputClient::CanComposeInline() const { + return false; +} + +gfx::Rect DummyTextInputClient::GetCaretBounds() { + return gfx::Rect(); +} + +bool DummyTextInputClient::GetCompositionCharacterBounds(uint32 index, + gfx::Rect* rect) { + return false; +} + +bool DummyTextInputClient::HasCompositionText() { + return false; +} + +bool DummyTextInputClient::GetTextRange(gfx::Range* range) { + return false; +} + +bool DummyTextInputClient::GetCompositionTextRange(gfx::Range* range) { + return false; +} + +bool DummyTextInputClient::GetSelectionRange(gfx::Range* range) { + return false; +} + +bool DummyTextInputClient::SetSelectionRange(const gfx::Range& range) { + return false; +} + +bool DummyTextInputClient::DeleteRange(const gfx::Range& range) { + return false; +} + +bool DummyTextInputClient::GetTextFromRange(const gfx::Range& range, + string16* text) { + return false; +} + +void DummyTextInputClient::OnInputMethodChanged() { +} + +bool DummyTextInputClient::ChangeTextDirectionAndLayoutAlignment( + base::i18n::TextDirection direction) { + return false; +} + +void DummyTextInputClient::ExtendSelectionAndDelete(size_t before, + size_t after) { +} + +void DummyTextInputClient::EnsureCaretInRect(const gfx::Rect& rect) { +} + +} // namespace ui diff --git a/chromium/ui/base/ime/dummy_text_input_client.h b/chromium/ui/base/ime/dummy_text_input_client.h new file mode 100644 index 00000000000..966502faa92 --- /dev/null +++ b/chromium/ui/base/ime/dummy_text_input_client.h @@ -0,0 +1,49 @@ +// 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. + +#ifndef UI_BASE_IME_DUMMY_TEXT_INPUT_CLIENT_H_ +#define UI_BASE_IME_DUMMY_TEXT_INPUT_CLIENT_H_ + +#include "ui/base/ime/text_input_client.h" + +namespace ui { + +// Dummy implementation of TextInputClient. All functions do nothing. +class DummyTextInputClient : public TextInputClient { + public: + DummyTextInputClient(); + virtual ~DummyTextInputClient(); + + // Overriden from TextInputClient. + virtual void SetCompositionText( + const ui::CompositionText& composition) OVERRIDE; + virtual void ConfirmCompositionText() OVERRIDE; + virtual void ClearCompositionText() OVERRIDE; + virtual void InsertText(const string16& text) OVERRIDE; + virtual void InsertChar(char16 ch, int flags) OVERRIDE; + virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE; + virtual ui::TextInputType GetTextInputType() const OVERRIDE; + virtual ui::TextInputMode GetTextInputMode() const OVERRIDE; + virtual bool CanComposeInline() const OVERRIDE; + virtual gfx::Rect GetCaretBounds() OVERRIDE; + virtual bool GetCompositionCharacterBounds(uint32 index, + gfx::Rect* rect) OVERRIDE; + virtual bool HasCompositionText() OVERRIDE; + virtual bool GetTextRange(gfx::Range* range) OVERRIDE; + virtual bool GetCompositionTextRange(gfx::Range* range) OVERRIDE; + virtual bool GetSelectionRange(gfx::Range* range) OVERRIDE; + virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE; + virtual bool DeleteRange(const gfx::Range& range) OVERRIDE; + virtual bool GetTextFromRange(const gfx::Range& range, + string16* text) OVERRIDE; + virtual void OnInputMethodChanged() OVERRIDE; + virtual bool ChangeTextDirectionAndLayoutAlignment( + base::i18n::TextDirection direction) OVERRIDE; + virtual void ExtendSelectionAndDelete(size_t before, size_t after) OVERRIDE; + virtual void EnsureCaretInRect(const gfx::Rect& rect) OVERRIDE; +}; + +} // namespace ui + +#endif // UI_BASE_IME_DUMMY_TEXT_INPUT_CLIENT_H_ diff --git a/chromium/ui/base/ime/fake_input_method.cc b/chromium/ui/base/ime/fake_input_method.cc index 1cf236de56b..21736168392 100644 --- a/chromium/ui/base/ime/fake_input_method.cc +++ b/chromium/ui/base/ime/fake_input_method.cc @@ -6,19 +6,19 @@ #include "base/logging.h" #include "base/strings/string16.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/events/event_utils.h" #include "ui/base/glib/glib_integers.h" #include "ui/base/ime/input_method_delegate.h" #include "ui/base/ime/text_input_client.h" -#include "ui/base/keycodes/keyboard_code_conversion.h" +#include "ui/events/event.h" +#include "ui/events/event_constants.h" +#include "ui/events/event_utils.h" +#include "ui/events/keycodes/keyboard_code_conversion.h" #if defined(USE_X11) #include <X11/X.h> #include <X11/Xlib.h> #include <X11/Xutil.h> -#include "ui/base/keycodes/keyboard_code_conversion_x.h" +#include "ui/events/keycodes/keyboard_code_conversion_x.h" #endif namespace { @@ -38,7 +38,8 @@ namespace ui { FakeInputMethod::FakeInputMethod(internal::InputMethodDelegate* delegate) : delegate_(NULL), - text_input_client_(NULL) { + text_input_client_(NULL), + is_sticky_text_input_client_(false) { SetDelegate(delegate); } @@ -50,11 +51,29 @@ void FakeInputMethod::SetDelegate(internal::InputMethodDelegate* delegate) { } void FakeInputMethod::SetFocusedTextInputClient(TextInputClient* client) { + if (is_sticky_text_input_client_) + return; text_input_client_ = client; FOR_EACH_OBSERVER(InputMethodObserver, observers_, OnTextInputStateChanged(client)); } +void FakeInputMethod::SetStickyFocusedTextInputClient(TextInputClient* client) { + text_input_client_ = client; + is_sticky_text_input_client_ = (client != NULL); + FOR_EACH_OBSERVER(InputMethodObserver, observers_, + OnTextInputStateChanged(client)); +} + +void FakeInputMethod::DetachTextInputClient(TextInputClient* client) { + if (text_input_client_ == client) { + text_input_client_ = NULL; + is_sticky_text_input_client_ = false; + FOR_EACH_OBSERVER(InputMethodObserver, observers_, + OnTextInputStateChanged(client)); + } +} + TextInputClient* FakeInputMethod::GetTextInputClient() const { return text_input_client_; } @@ -92,6 +111,27 @@ bool FakeInputMethod::DispatchKeyEvent(const base::NativeEvent& native_event) { text_input_client_->InsertChar(ch, state); } } +#elif defined(USE_OZONE) + DCHECK(native_event); + if (EventTypeFromNative(native_event) == ET_KEY_RELEASED) { + // On key release, just dispatch it. + handled = delegate_->DispatchKeyEventPostIME(native_event); + } else { + const uint32 state = EventFlagsFromNative(native_event); + // Send a RawKeyDown event first, + handled = delegate_->DispatchKeyEventPostIME(native_event); + if (text_input_client_) { + // then send a Char event via ui::TextInputClient. + const KeyboardCode key_code = ui::KeyboardCodeFromNative(native_event); + uint16 ch = 0; + + // TODO(vignatti): Support EF_CONTROL_DOWN state + + ch = ui::GetCharacterFromKeyCode(key_code, state); + if (ch) + text_input_client_->InsertChar(ch, state); + } + } #else // TODO(yusukes): Support other platforms. Call InsertChar() when necessary. handled = delegate_->DispatchKeyEventPostIME(native_event); @@ -141,8 +181,12 @@ bool FakeInputMethod::IsCandidatePopupOpen() const { return false; } -ui::TextInputType FakeInputMethod::GetTextInputType() const { - return ui::TEXT_INPUT_TYPE_NONE; +TextInputType FakeInputMethod::GetTextInputType() const { + return TEXT_INPUT_TYPE_NONE; +} + +TextInputMode FakeInputMethod::GetTextInputMode() const { + return TEXT_INPUT_MODE_DEFAULT; } bool FakeInputMethod::CanComposeInline() const { diff --git a/chromium/ui/base/ime/fake_input_method.h b/chromium/ui/base/ime/fake_input_method.h index 12f9aac0180..42b8b024978 100644 --- a/chromium/ui/base/ime/fake_input_method.h +++ b/chromium/ui/base/ime/fake_input_method.h @@ -34,6 +34,9 @@ class UI_EXPORT FakeInputMethod : NON_EXPORTED_BASE(public InputMethod) { virtual bool OnUntranslatedIMEMessage(const base::NativeEvent& event, NativeEventResult* result) OVERRIDE; virtual void SetFocusedTextInputClient(TextInputClient* client) OVERRIDE; + virtual void SetStickyFocusedTextInputClient( + TextInputClient* client) OVERRIDE; + virtual void DetachTextInputClient(TextInputClient* client) OVERRIDE; virtual TextInputClient* GetTextInputClient() const OVERRIDE; virtual bool DispatchKeyEvent(const base::NativeEvent& native_event) OVERRIDE; virtual bool DispatchFabricatedKeyEvent(const ui::KeyEvent& event) OVERRIDE; @@ -44,7 +47,8 @@ class UI_EXPORT FakeInputMethod : NON_EXPORTED_BASE(public InputMethod) { virtual std::string GetInputLocale() OVERRIDE; virtual base::i18n::TextDirection GetInputTextDirection() OVERRIDE; virtual bool IsActive() OVERRIDE; - virtual ui::TextInputType GetTextInputType() const OVERRIDE; + virtual TextInputType GetTextInputType() const OVERRIDE; + virtual TextInputMode GetTextInputMode() const OVERRIDE; virtual bool CanComposeInline() const OVERRIDE; virtual bool IsCandidatePopupOpen() const OVERRIDE; virtual void AddObserver(InputMethodObserver* observer) OVERRIDE; @@ -53,6 +57,7 @@ class UI_EXPORT FakeInputMethod : NON_EXPORTED_BASE(public InputMethod) { private: internal::InputMethodDelegate* delegate_; TextInputClient* text_input_client_; + bool is_sticky_text_input_client_; ObserverList<InputMethodObserver> observers_; DISALLOW_COPY_AND_ASSIGN(FakeInputMethod); diff --git a/chromium/ui/base/ime/ime.gypi b/chromium/ui/base/ime/ime.gypi index b8a18963588..70c5cd0f306 100644 --- a/chromium/ui/base/ime/ime.gypi +++ b/chromium/ui/base/ime/ime.gypi @@ -10,6 +10,8 @@ 'composition_text.cc', 'composition_text.h', 'composition_underline.h', + 'dummy_input_method_delegate.cc', + 'dummy_input_method_delegate.h', 'input_method.h', 'input_method_base.cc', 'input_method_base.h', diff --git a/chromium/ui/base/ime/ime_test_support.gypi b/chromium/ui/base/ime/ime_test_support.gypi index a6ac3615261..02fa6eb1191 100644 --- a/chromium/ui/base/ime/ime_test_support.gypi +++ b/chromium/ui/base/ime/ime_test_support.gypi @@ -6,6 +6,8 @@ 'sources': [ 'dummy_input_method.cc', 'dummy_input_method.h', + 'dummy_text_input_client.cc', + 'dummy_text_input_client.h', 'win/mock_tsf_bridge.cc', 'win/mock_tsf_bridge.h', ], diff --git a/chromium/ui/base/ime/ime_unittests.gypi b/chromium/ui/base/ime/ime_unittests.gypi index 173e74c9063..3dabb50eda3 100644 --- a/chromium/ui/base/ime/ime_unittests.gypi +++ b/chromium/ui/base/ime/ime_unittests.gypi @@ -3,27 +3,29 @@ # found in the LICENSE file. { - 'variables': { - 'ime_test_files': [ - 'character_composer_unittest.cc', - 'input_method_ibus_unittest.cc', - ], - }, 'sources': [ - '<@(ime_test_files)', + 'character_composer_unittest.cc', + 'input_method_base_unittest.cc', + 'input_method_ibus_unittest.cc', 'win/imm32_manager_unittest.cc', + 'win/tsf_input_scope_unittest.cc', 'win/tsf_text_store_unittest.cc', ], 'conditions': [ ['use_aura==0 or use_x11==0 or chromeos==0', { 'sources!': [ - '<@(ime_test_files)', + 'character_composer_unittest.cc', + 'input_method_ibus_unittest.cc', ], }], - ['OS!="win"', { + ['use_aura==0 and OS!="win"', { 'sources!': [ - 'win/imm32_manager_unittest.cc', - 'win/tsf_text_store_unittest.cc', + 'input_method_base_unittest.cc', + ], + }], + ['OS!="win"', { + 'sources/': [ + ['exclude', '^win'], ], }], ], diff --git a/chromium/ui/base/ime/input_method.h b/chromium/ui/base/ime/input_method.h index 575cbcdb305..ac24f77af16 100644 --- a/chromium/ui/base/ime/input_method.h +++ b/chromium/ui/base/ime/input_method.h @@ -10,9 +10,10 @@ #include "base/basictypes.h" #include "base/event_types.h" #include "base/i18n/rtl.h" +#include "ui/base/ime/text_input_mode.h" #include "ui/base/ime/text_input_type.h" -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/base/ui_export.h" +#include "ui/events/keycodes/keyboard_codes.h" namespace ui { @@ -82,9 +83,22 @@ class InputMethod { // SetCompositionText(). |client| can be NULL. A gfx::NativeWindow which // implementes TextInputClient interface, e.g. NWA and RWHVA, should register // itself by calling the method when it is focused, and unregister itself by - // calling the metho with NULL when it is unfocused. + // calling the method with NULL when it is unfocused. virtual void SetFocusedTextInputClient(TextInputClient* client) = 0; + // A variant of SetFocusedTextInputClient. Unlike SetFocusedTextInputClient, + // all the subsequent calls of SetFocusedTextInputClient will be ignored + // until |client| is detached. This method is introduced as a workaround + // against crbug.com/287620. + // NOTE: You can pass NULL to |client| to detach the sticky client. + // NOTE: You can also use DetachTextInputClient to remove the sticky client. + virtual void SetStickyFocusedTextInputClient(TextInputClient* client) = 0; + + // Detaches and forgets the |client| regardless of whether it has the focus or + // not. This method is meant to be called when the |client| is going to be + // destroyed. + virtual void DetachTextInputClient(TextInputClient* client) = 0; + // Gets the current text input client. Returns NULL when no client is set. virtual TextInputClient* GetTextInputClient() const = 0; @@ -140,10 +154,18 @@ class InputMethod { // is not active. virtual bool IsActive() = 0; + // TODO(yoichio): Following 3 methods(GetTextInputType, GetTextInputMode and + // CanComposeInline) calls client's same method and returns its value. It is + // not InputMethod itself's infomation. So rename these to + // GetClientTextInputType and so on. // Gets the text input type of the focused text input client. Returns // ui::TEXT_INPUT_TYPE_NONE if there is no focused client. virtual TextInputType GetTextInputType() const = 0; + // Gets the text input mode of the focused text input client. Returns + // ui::TEXT_INPUT_TYPE_DEFAULT if there is no focused client. + virtual TextInputMode GetTextInputMode() const = 0; + // Checks if the focused text input client supports inline composition. virtual bool CanComposeInline() const = 0; diff --git a/chromium/ui/base/ime/input_method_base.cc b/chromium/ui/base/ime/input_method_base.cc index 6972eed9258..d3770765340 100644 --- a/chromium/ui/base/ime/input_method_base.cc +++ b/chromium/ui/base/ime/input_method_base.cc @@ -14,6 +14,7 @@ namespace ui { InputMethodBase::InputMethodBase() : delegate_(NULL), text_input_client_(NULL), + is_sticky_text_input_client_(false), system_toplevel_window_focused_(false) { } @@ -43,13 +44,24 @@ void InputMethodBase::OnBlur() { } void InputMethodBase::SetFocusedTextInputClient(TextInputClient* client) { - TextInputClient* old = text_input_client_; - OnWillChangeFocusedClient(old, client); - text_input_client_ = client; // NULL allowed. - OnDidChangeFocusedClient(old, client); + if (is_sticky_text_input_client_) + return; + SetFocusedTextInputClientInternal(client); +} + +void InputMethodBase::SetStickyFocusedTextInputClient(TextInputClient* client) { + is_sticky_text_input_client_ = (client != NULL); + SetFocusedTextInputClientInternal(client); +} - if (old != text_input_client_) +void InputMethodBase::DetachTextInputClient(TextInputClient* client) { + if (text_input_client_ == client) { + OnWillChangeFocusedClient(client, NULL); + text_input_client_ = NULL; + is_sticky_text_input_client_ = false; + OnDidChangeFocusedClient(client, NULL); NotifyTextInputStateChanged(text_input_client_); + } } TextInputClient* InputMethodBase::GetTextInputClient() const { @@ -67,6 +79,11 @@ TextInputType InputMethodBase::GetTextInputType() const { return client ? client->GetTextInputType() : TEXT_INPUT_TYPE_NONE; } +TextInputMode InputMethodBase::GetTextInputMode() const { + TextInputClient* client = GetTextInputClient(); + return client ? client->GetTextInputMode() : TEXT_INPUT_MODE_DEFAULT; +} + bool InputMethodBase::CanComposeInline() const { TextInputClient* client = GetTextInputClient(); return client ? client->CanComposeInline() : true; @@ -113,4 +130,15 @@ void InputMethodBase::NotifyTextInputStateChanged( OnTextInputStateChanged(client)); } +void InputMethodBase::SetFocusedTextInputClientInternal( + TextInputClient* client) { + TextInputClient* old = text_input_client_; + if (old == client) + return; + OnWillChangeFocusedClient(old, client); + text_input_client_ = client; // NULL allowed. + OnDidChangeFocusedClient(old, client); + NotifyTextInputStateChanged(text_input_client_); +} + } // namespace ui diff --git a/chromium/ui/base/ime/input_method_base.h b/chromium/ui/base/ime/input_method_base.h index e467e0bec8e..665070a9c78 100644 --- a/chromium/ui/base/ime/input_method_base.h +++ b/chromium/ui/base/ime/input_method_base.h @@ -8,9 +8,9 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/observer_list.h" -#include "ui/base/events/event_constants.h" #include "ui/base/ime/input_method.h" #include "ui/base/ui_export.h" +#include "ui/events/event_constants.h" namespace gfx { class Rect; @@ -37,6 +37,9 @@ class UI_EXPORT InputMethodBase : NON_EXPORTED_BASE(public InputMethod) { virtual void OnFocus() OVERRIDE; virtual void OnBlur() OVERRIDE; virtual void SetFocusedTextInputClient(TextInputClient* client) OVERRIDE; + virtual void SetStickyFocusedTextInputClient( + TextInputClient* client) OVERRIDE; + virtual void DetachTextInputClient(TextInputClient* client) OVERRIDE; virtual TextInputClient* GetTextInputClient() const OVERRIDE; // If a derived class overrides this method, it should call parent's @@ -44,6 +47,7 @@ class UI_EXPORT InputMethodBase : NON_EXPORTED_BASE(public InputMethod) { virtual void OnTextInputTypeChanged(const TextInputClient* client) OVERRIDE; virtual TextInputType GetTextInputType() const OVERRIDE; + virtual TextInputMode GetTextInputMode() const OVERRIDE; virtual bool CanComposeInline() const OVERRIDE; virtual void AddObserver(InputMethodObserver* observer) OVERRIDE; @@ -86,8 +90,11 @@ class UI_EXPORT InputMethodBase : NON_EXPORTED_BASE(public InputMethod) { } private: + void SetFocusedTextInputClientInternal(TextInputClient* client); + internal::InputMethodDelegate* delegate_; TextInputClient* text_input_client_; + bool is_sticky_text_input_client_; ObserverList<InputMethodObserver> observer_list_; diff --git a/chromium/ui/base/ime/input_method_base_unittest.cc b/chromium/ui/base/ime/input_method_base_unittest.cc new file mode 100644 index 00000000000..cc7304cefcc --- /dev/null +++ b/chromium/ui/base/ime/input_method_base_unittest.cc @@ -0,0 +1,383 @@ +// 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 "ui/base/ime/input_method_base.h" + +#include "base/scoped_observer.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/ime/dummy_text_input_client.h" +#include "ui/base/ime/input_method_observer.h" +#include "ui/events/event.h" + +namespace ui { +namespace { + +class ClientChangeVerifier { + public: + ClientChangeVerifier() + : previous_client_(NULL), + next_client_(NULL), + call_expected_(false), + on_will_change_focused_client_called_(false), + on_did_change_focused_client_called_(false), + on_text_input_state_changed_(false) { + } + + // Expects that focused text input client will not be changed. + void ExpectClientDoesNotChange() { + previous_client_ = NULL; + next_client_ = NULL; + call_expected_ = false; + on_will_change_focused_client_called_ = false; + on_did_change_focused_client_called_ = false; + on_text_input_state_changed_ = false; + } + + // Expects that focused text input client will be changed from + // |previous_client| to |next_client|. + void ExpectClientChange(TextInputClient* previous_client, + TextInputClient* next_client) { + previous_client_ = previous_client; + next_client_ = next_client; + call_expected_ = true; + on_will_change_focused_client_called_ = false; + on_did_change_focused_client_called_ = false; + on_text_input_state_changed_ = false; + } + + // Verifies the result satisfies the expectation or not. + void Verify() { + EXPECT_EQ(call_expected_, on_will_change_focused_client_called_); + EXPECT_EQ(call_expected_, on_did_change_focused_client_called_); + EXPECT_EQ(call_expected_, on_text_input_state_changed_); + } + + void OnWillChangeFocusedClient(TextInputClient* focused_before, + TextInputClient* focused) { + EXPECT_TRUE(call_expected_); + + // Check arguments + EXPECT_EQ(previous_client_, focused_before); + EXPECT_EQ(next_client_, focused); + + // Check call order + EXPECT_FALSE(on_will_change_focused_client_called_); + EXPECT_FALSE(on_did_change_focused_client_called_); + EXPECT_FALSE(on_text_input_state_changed_); + + on_will_change_focused_client_called_ = true; + } + + void OnDidChangeFocusedClient(TextInputClient* focused_before, + TextInputClient* focused) { + EXPECT_TRUE(call_expected_); + + // Check arguments + EXPECT_EQ(previous_client_, focused_before); + EXPECT_EQ(next_client_, focused); + + // Check call order + EXPECT_TRUE(on_will_change_focused_client_called_); + EXPECT_FALSE(on_did_change_focused_client_called_); + EXPECT_FALSE(on_text_input_state_changed_); + + on_did_change_focused_client_called_ = true; + } + + void OnTextInputStateChanged(const TextInputClient* client) { + EXPECT_TRUE(call_expected_); + + // Check arguments + EXPECT_EQ(next_client_, client); + + // Check call order + EXPECT_TRUE(on_will_change_focused_client_called_); + EXPECT_TRUE(on_did_change_focused_client_called_); + EXPECT_FALSE(on_text_input_state_changed_); + + on_text_input_state_changed_ = true; + } + + private: + TextInputClient* previous_client_; + TextInputClient* next_client_; + bool call_expected_; + bool on_will_change_focused_client_called_; + bool on_did_change_focused_client_called_; + bool on_text_input_state_changed_; + + DISALLOW_COPY_AND_ASSIGN(ClientChangeVerifier); +}; + +class MockInputMethodBase : public InputMethodBase { + public: + // Note: this class does not take the ownership of |verifier|. + explicit MockInputMethodBase(ClientChangeVerifier* verifier) + : verifier_(verifier) { + } + virtual ~MockInputMethodBase() { + } + + private: + // Overriden from InputMethod. + virtual bool OnUntranslatedIMEMessage( + const base::NativeEvent& event, + InputMethod::NativeEventResult* result) OVERRIDE { + return false; + } + virtual bool DispatchKeyEvent(const base::NativeEvent&) OVERRIDE { + return false; + } + virtual bool DispatchFabricatedKeyEvent(const ui::KeyEvent&) OVERRIDE { + return false; + } + virtual void OnCaretBoundsChanged(const TextInputClient* clien) OVERRIDE { + } + virtual void CancelComposition(const TextInputClient* clien) OVERRIDE { + } + virtual void OnInputLocaleChanged() OVERRIDE { + } + virtual std::string GetInputLocale() OVERRIDE { + return ""; + } + virtual base::i18n::TextDirection GetInputTextDirection() OVERRIDE { + return base::i18n::UNKNOWN_DIRECTION; + } + virtual bool IsActive() OVERRIDE { + return false; + } + virtual bool IsCandidatePopupOpen() const OVERRIDE { + return false; + } + + // Overriden from InputMethodBase. + virtual void OnWillChangeFocusedClient(TextInputClient* focused_before, + TextInputClient* focused) OVERRIDE { + verifier_->OnWillChangeFocusedClient(focused_before, focused); + } + + virtual void OnDidChangeFocusedClient(TextInputClient* focused_before, + TextInputClient* focused) OVERRIDE { + verifier_->OnDidChangeFocusedClient(focused_before, focused); + } + + ClientChangeVerifier* verifier_; + DISALLOW_COPY_AND_ASSIGN(MockInputMethodBase); +}; + +class MockInputMethodObserver : public InputMethodObserver { + public: + // Note: this class does not take the ownership of |verifier|. + explicit MockInputMethodObserver(ClientChangeVerifier* verifier) + : verifier_(verifier) { + } + virtual ~MockInputMethodObserver() { + } + + private: + virtual void OnTextInputStateChanged(const TextInputClient* client) OVERRIDE { + verifier_->OnTextInputStateChanged(client); + } + virtual void OnInputMethodDestroyed(const InputMethod* client) OVERRIDE { + } + + ClientChangeVerifier* verifier_; + DISALLOW_COPY_AND_ASSIGN(MockInputMethodObserver); +}; + +typedef ScopedObserver<InputMethod, InputMethodObserver> + InputMethodScopedObserver; + +TEST(InputMethodBaseTest, SetFocusedTextInputClient) { + DummyTextInputClient text_input_client_1st; + DummyTextInputClient text_input_client_2nd; + + ClientChangeVerifier verifier; + MockInputMethodBase input_method(&verifier); + MockInputMethodObserver input_method_observer(&verifier); + InputMethodScopedObserver scoped_observer(&input_method_observer); + scoped_observer.Add(&input_method); + + // Assume that the top-level-widget gains focus. + input_method.OnFocus(); + + { + SCOPED_TRACE("Focus from NULL to 1st TextInputClient"); + + ASSERT_EQ(NULL, input_method.GetTextInputClient()); + verifier.ExpectClientChange(NULL, &text_input_client_1st); + input_method.SetFocusedTextInputClient(&text_input_client_1st); + EXPECT_EQ(&text_input_client_1st, input_method.GetTextInputClient()); + verifier.Verify(); + } + + { + SCOPED_TRACE("Redundant focus events must be ignored"); + verifier.ExpectClientDoesNotChange(); + input_method.SetFocusedTextInputClient(&text_input_client_1st); + verifier.Verify(); + } + + { + SCOPED_TRACE("Focus from 1st to 2nd TextInputClient"); + + ASSERT_EQ(&text_input_client_1st, input_method.GetTextInputClient()); + verifier.ExpectClientChange(&text_input_client_1st, + &text_input_client_2nd); + input_method.SetFocusedTextInputClient(&text_input_client_2nd); + EXPECT_EQ(&text_input_client_2nd, input_method.GetTextInputClient()); + verifier.Verify(); + } + + { + SCOPED_TRACE("Focus from 2nd TextInputClient to NULL"); + + ASSERT_EQ(&text_input_client_2nd, input_method.GetTextInputClient()); + verifier.ExpectClientChange(&text_input_client_2nd, NULL); + input_method.SetFocusedTextInputClient(NULL); + EXPECT_EQ(NULL, input_method.GetTextInputClient()); + verifier.Verify(); + } + + { + SCOPED_TRACE("Redundant focus events must be ignored"); + verifier.ExpectClientDoesNotChange(); + input_method.SetFocusedTextInputClient(NULL); + verifier.Verify(); + } +} + +TEST(InputMethodBaseTest, DetachTextInputClient) { + DummyTextInputClient text_input_client; + DummyTextInputClient text_input_client_the_other; + + ClientChangeVerifier verifier; + MockInputMethodBase input_method(&verifier); + MockInputMethodObserver input_method_observer(&verifier); + InputMethodScopedObserver scoped_observer(&input_method_observer); + scoped_observer.Add(&input_method); + + // Assume that the top-level-widget gains focus. + input_method.OnFocus(); + + // Initialize for the next test. + { + verifier.ExpectClientChange(NULL, &text_input_client); + input_method.SetFocusedTextInputClient(&text_input_client); + verifier.Verify(); + } + + { + SCOPED_TRACE("DetachTextInputClient must be ignored for other clients"); + ASSERT_EQ(&text_input_client, input_method.GetTextInputClient()); + verifier.ExpectClientDoesNotChange(); + input_method.DetachTextInputClient(&text_input_client_the_other); + EXPECT_EQ(&text_input_client, input_method.GetTextInputClient()); + verifier.Verify(); + } + + { + SCOPED_TRACE("DetachTextInputClient must succeed even after the " + "top-level loses the focus"); + + ASSERT_EQ(&text_input_client, input_method.GetTextInputClient()); + input_method.OnBlur(); + input_method.OnFocus(); + verifier.ExpectClientChange(&text_input_client, NULL); + input_method.DetachTextInputClient(&text_input_client); + EXPECT_EQ(NULL, input_method.GetTextInputClient()); + verifier.Verify(); + } +} + +TEST(InputMethodBaseTest, SetStickyFocusedTextInputClient) { + DummyTextInputClient sticky_client; + DummyTextInputClient non_sticky_client; + + ClientChangeVerifier verifier; + MockInputMethodBase input_method(&verifier); + MockInputMethodObserver input_method_observer(&verifier); + InputMethodScopedObserver scoped_observer(&input_method_observer); + scoped_observer.Add(&input_method); + + // Assume that the top-level-widget gains focus. + input_method.OnFocus(); + + { + SCOPED_TRACE("Focus from NULL to non-sticky client"); + + ASSERT_EQ(NULL, input_method.GetTextInputClient()); + verifier.ExpectClientChange(NULL, &non_sticky_client); + input_method.SetFocusedTextInputClient(&non_sticky_client); + EXPECT_EQ(&non_sticky_client, input_method.GetTextInputClient()); + verifier.Verify(); + } + + { + SCOPED_TRACE("Focus from non-sticky to sticky client"); + + ASSERT_EQ(&non_sticky_client, input_method.GetTextInputClient()); + verifier.ExpectClientChange(&non_sticky_client, &sticky_client); + input_method.SetStickyFocusedTextInputClient(&sticky_client); + EXPECT_EQ(&sticky_client, input_method.GetTextInputClient()); + verifier.Verify(); + } + + { + SCOPED_TRACE("Focus from sticky to non-sticky client -> must fail"); + + ASSERT_EQ(&sticky_client, input_method.GetTextInputClient()); + verifier.ExpectClientDoesNotChange(); + input_method.SetFocusedTextInputClient(&non_sticky_client); + EXPECT_EQ(&sticky_client, input_method.GetTextInputClient()); + verifier.Verify(); + } + + { + SCOPED_TRACE("Focus from sticky to NULL -> must fail"); + + verifier.ExpectClientDoesNotChange(); + input_method.SetFocusedTextInputClient(NULL); + EXPECT_EQ(&sticky_client, input_method.GetTextInputClient()); + verifier.Verify(); + } + + { + SCOPED_TRACE("SetStickyFocusedTextInputClient(NULL) must be supported"); + + ASSERT_EQ(&sticky_client, input_method.GetTextInputClient()); + verifier.ExpectClientChange(&sticky_client, NULL); + input_method.SetStickyFocusedTextInputClient(NULL); + EXPECT_EQ(NULL, input_method.GetTextInputClient()); + verifier.Verify(); + + // |SetStickyFocusedTextInputClient(NULL)| must be equivalent to + // |SetFocusedTextInputClient(NULL)|. We should be able to use + // |SetFocusedTextInputClient(&non_sticky_client)| here. + verifier.ExpectClientChange(NULL, &non_sticky_client); + input_method.SetFocusedTextInputClient(&non_sticky_client); + EXPECT_EQ(&non_sticky_client, input_method.GetTextInputClient()); + verifier.Verify(); + } + + { + SCOPED_TRACE("Set stick client again for the next test"); + verifier.ExpectClientChange(&non_sticky_client, &sticky_client); + input_method.SetStickyFocusedTextInputClient(&sticky_client); + verifier.Verify(); + } + + { + SCOPED_TRACE("DetachTextInputClient must be supported for sticky client"); + + ASSERT_EQ(&sticky_client, input_method.GetTextInputClient()); + verifier.ExpectClientChange(&sticky_client, NULL); + input_method.DetachTextInputClient(&sticky_client); + EXPECT_EQ(NULL, input_method.GetTextInputClient()); + verifier.Verify(); + } +} + +} // namespace +} // namespace ui diff --git a/chromium/ui/base/ime/input_method_delegate.h b/chromium/ui/base/ime/input_method_delegate.h index c0846b1c039..21319437d65 100644 --- a/chromium/ui/base/ime/input_method_delegate.h +++ b/chromium/ui/base/ime/input_method_delegate.h @@ -6,9 +6,9 @@ #define UI_BASE_IME_INPUT_METHOD_DELEGATE_H_ #include "base/event_types.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/base/ui_export.h" +#include "ui/events/event_constants.h" +#include "ui/events/keycodes/keyboard_codes.h" namespace ui { namespace internal { diff --git a/chromium/ui/base/ime/input_method_ibus.cc b/chromium/ui/base/ime/input_method_ibus.cc index 7c4f803d445..8ff645a2130 100644 --- a/chromium/ui/base/ime/input_method_ibus.cc +++ b/chromium/ui/base/ime/input_method_ibus.cc @@ -23,30 +23,21 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/third_party/icu/icu_utf.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/ibus/ibus_client.h" -#include "chromeos/dbus/ibus/ibus_input_context_client.h" #include "chromeos/dbus/ibus/ibus_text.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/events/event_utils.h" +#include "chromeos/ime/input_method_descriptor.h" +#include "chromeos/ime/input_method_manager.h" #include "ui/base/ime/text_input_client.h" -#include "ui/base/keycodes/keyboard_code_conversion.h" -#include "ui/base/keycodes/keyboard_code_conversion_x.h" -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/event.h" +#include "ui/events/event_constants.h" +#include "ui/events/event_utils.h" +#include "ui/events/keycodes/keyboard_code_conversion.h" +#include "ui/events/keycodes/keyboard_code_conversion_x.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/rect.h" namespace { const int kIBusReleaseMask = 1 << 30; -const char kClientName[] = "chrome"; -const int kMaxRetryCount = 10; - -// Following capability mask is introduced from -// http://ibus.googlecode.com/svn/docs/ibus-1.4/ibus-ibustypes.html#IBusCapabilite -const uint32 kIBusCapabilityPreeditText = 1U; -const uint32 kIBusCapabilityFocus = 8U; -const uint32 kIBusCapabilitySurroundingText = 32U; XKeyEvent* GetKeyEvent(XEvent* event) { DCHECK(event && (event->type == KeyPress || event->type == KeyRelease)); @@ -70,15 +61,15 @@ uint32 IBusStateFromXState(unsigned int state) { Button1Mask | Button2Mask | Button3Mask)); } -chromeos::IBusInputContextClient* GetInputContextClient() { - return chromeos::DBusThreadManager::Get()->GetIBusInputContextClient(); -} - // Converts gfx::Rect to ibus::Rect. chromeos::ibus::Rect GfxRectToIBusRect(const gfx::Rect& rect) { return chromeos::ibus::Rect(rect.x(), rect.y(), rect.width(), rect.height()); } +chromeos::IBusEngineHandlerInterface* GetEngine() { + return chromeos::IBusBridge::Get()->GetEngineHandler(); +} + } // namespace namespace ui { @@ -86,33 +77,28 @@ namespace ui { // InputMethodIBus implementation ----------------------------------------- InputMethodIBus::InputMethodIBus( internal::InputMethodDelegate* delegate) - : input_context_state_(INPUT_CONTEXT_STOP), - create_input_context_fail_count_(0), - context_focused_(false), + : context_focused_(false), composing_text_(false), composition_changed_(false), suppress_next_result_(false), current_keyevent_id_(0), + previous_textinput_type_(TEXT_INPUT_TYPE_NONE), weak_ptr_factory_(this) { SetDelegate(delegate); + chromeos::IBusBridge::Get()->SetInputContextHandler(this); - // chromeos::IBusDaemonController is not available in case of some testing, - // e.g. content_browser test can't initialize IBusDaemonController. - DCHECK(!base::chromeos::IsRunningOnChromeOS() || - chromeos::IBusDaemonController::GetInstance()); - - if (chromeos::IBusDaemonController::GetInstance()) - chromeos::IBusDaemonController::GetInstance()->AddObserver(this); + UpdateContextFocusState(); + OnInputMethodChanged(); } InputMethodIBus::~InputMethodIBus() { AbandonAllPendingKeyEvents(); - if (IsContextReady()) - DestroyContext(); - if (GetInputContextClient()) - GetInputContextClient()->SetInputContextHandler(NULL); - if (chromeos::IBusDaemonController::GetInstance()) - chromeos::IBusDaemonController::GetInstance()->RemoveObserver(this); + context_focused_ = false; + ConfirmCompositionText(); + // We are dead, so we need to ask the client to stop relying on us. + OnInputMethodChanged(); + + chromeos::IBusBridge::Get()->SetInputContextHandler(NULL); } void InputMethodIBus::OnFocus() { @@ -131,18 +117,6 @@ bool InputMethodIBus::OnUntranslatedIMEMessage(const base::NativeEvent& event, return false; } -void InputMethodIBus::Init(bool focused) { - // Initializes the connection to ibus daemon. It may happen asynchronously, - // and as soon as the connection is established, the |context_| will be - // created automatically. - - // Create the input context if the connection is already established. - if (IsConnected()) - CreateContext(); - - InputMethodBase::Init(focused); -} - void InputMethodIBus::ProcessKeyEventDone(uint32 id, XEvent* event, uint32 ibus_keyval, @@ -193,10 +167,8 @@ bool InputMethodIBus::DispatchKeyEvent(const base::NativeEvent& native_event) { // TEXT_INPUT_TYPE_PASSWORD, to bypass the input method. // Note: We need to send the key event to ibus even if the |context_| is not // enabled, so that ibus can have a chance to enable the |context_|. - if (!context_focused_ || - GetTextInputType() == TEXT_INPUT_TYPE_PASSWORD || - !GetInputContextClient() || - GetInputContextClient()->IsXKBLayout()) { + if (!context_focused_ || !GetEngine() || + GetTextInputType() == TEXT_INPUT_TYPE_PASSWORD ) { if (native_event->type == KeyPress) { if (ExecuteCharacterComposer(ibus_keyval, ibus_keycode, ibus_state)) { // Treating as PostIME event if character composer handles key event and @@ -214,24 +186,22 @@ bool InputMethodIBus::DispatchKeyEvent(const base::NativeEvent& native_event) { pending_key_events_.insert(current_keyevent_id_); // Since |native_event| might be treated as XEvent whose size is bigger than - // XKeyEvent e.g. in CopyNativeEvent() in ui/base/events/event.cc, allocating + // XKeyEvent e.g. in CopyNativeEvent() in ui/events/event.cc, allocating // |event| as XKeyEvent and casting it to XEvent is unsafe. crbug.com/151884 XEvent* event = new XEvent; *event = *native_event; - const chromeos::IBusInputContextClient::ProcessKeyEventCallback callback = + GetEngine()->ProcessKeyEvent( + ibus_keyval, + ibus_keycode, + ibus_state, base::Bind(&InputMethodIBus::ProcessKeyEventDone, weak_ptr_factory_.GetWeakPtr(), current_keyevent_id_, base::Owned(event), // Pass the ownership of |event|. ibus_keyval, ibus_keycode, - ibus_state); + ibus_state)); - GetInputContextClient()->ProcessKeyEvent(ibus_keyval, - ibus_keycode, - ibus_state, - callback, - base::Bind(callback, false)); ++current_keyevent_id_; // We don't want to suppress the result generated by this key event, but it @@ -255,9 +225,11 @@ bool InputMethodIBus::DispatchFabricatedKeyEvent(const ui::KeyEvent& event) { } void InputMethodIBus::OnTextInputTypeChanged(const TextInputClient* client) { - if (IsContextReady() && IsTextInputClientFocused(client)) { + if (IsTextInputClientFocused(client)) { ResetContext(); UpdateContextFocusState(); + if (previous_textinput_type_ != client->GetTextInputType()) + OnInputMethodChanged(); } InputMethodBase::OnTextInputTypeChanged(client); } @@ -276,18 +248,22 @@ void InputMethodIBus::OnCaretBoundsChanged(const TextInputClient* client) { composition_head = rect; } - GetInputContextClient()->SetCursorLocation( + chromeos::IBusPanelCandidateWindowHandlerInterface* candidate_window = + chromeos::IBusBridge::Get()->GetCandidateWindowHandler(); + if (!candidate_window) + return; + candidate_window->SetCursorLocation( GfxRectToIBusRect(rect), GfxRectToIBusRect(composition_head)); - ui::Range text_range; - ui::Range selection_range; + gfx::Range text_range; + gfx::Range selection_range; string16 surrounding_text; if (!GetTextInputClient()->GetTextRange(&text_range) || !GetTextInputClient()->GetTextFromRange(text_range, &surrounding_text) || !GetTextInputClient()->GetSelectionRange(&selection_range)) { previous_surrounding_text_.clear(); - previous_selection_range_ = ui::Range::InvalidRange(); + previous_selection_range_ = gfx::Range::InvalidRange(); return; } @@ -308,7 +284,9 @@ void InputMethodIBus::OnCaretBoundsChanged(const TextInputClient* client) { // Here SetSurroundingText accepts relative position of |surrounding_text|, so // we have to convert |selection_range| from node coordinates to // |surrounding_text| coordinates. - GetInputContextClient()->SetSurroundingText( + if (!GetEngine()) + return; + GetEngine()->SetSurroundingText( UTF16ToUTF8(surrounding_text), selection_range.start() - text_range.start(), selection_range.end() - text_range.start()); @@ -360,61 +338,6 @@ void InputMethodIBus::OnDidChangeFocusedClient(TextInputClient* focused_before, OnCaretBoundsChanged(focused); } -void InputMethodIBus::CreateContext() { - DCHECK(IsConnected()); - - if (input_context_state_ != INPUT_CONTEXT_STOP) { - DVLOG(1) << "Input context is already created or waiting ibus-daemon" - " response."; - return; - } - - input_context_state_ = INPUT_CONTEXT_WAIT_CREATE_INPUT_CONTEXT_RESPONSE; - - // Creates the input context asynchronously. - DCHECK(!IsContextReady()); - chromeos::DBusThreadManager::Get()->GetIBusClient()->CreateInputContext( - kClientName, - base::Bind(&InputMethodIBus::CreateInputContextDone, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&InputMethodIBus::CreateInputContextFail, - weak_ptr_factory_.GetWeakPtr())); -} - -void InputMethodIBus::SetUpSignalHandlers() { - DCHECK(IsContextReady()); - - // We should reset the handler to NULL before |this| is deleted so handler - // functions are not called after |this| is deleted. - GetInputContextClient()->SetInputContextHandler(this); - - GetInputContextClient()->SetCapabilities( - kIBusCapabilityPreeditText | kIBusCapabilityFocus | - kIBusCapabilitySurroundingText); - - UpdateContextFocusState(); - // Since ibus-daemon is launched in an on-demand basis on Chrome OS, RWHVA (or - // equivalents) might call OnCaretBoundsChanged() before the daemon starts. To - // save the case, call OnCaretBoundsChanged() here. - OnCaretBoundsChanged(GetTextInputClient()); - OnInputMethodChanged(); -} - -void InputMethodIBus::DestroyContext() { - if (input_context_state_ == INPUT_CONTEXT_STOP) - return; - input_context_state_ = INPUT_CONTEXT_STOP; - chromeos::IBusInputContextClient* input_context = GetInputContextClient(); - if (!input_context) - return; - if (input_context->IsObjectProxyReady()) { - // We can't use IsContextReady here because we want to destroy object proxy - // regardless of connection. The IsContextReady contains connection check. - ResetInputContext(); - DCHECK(!IsContextReady()); - } -} - void InputMethodIBus::ConfirmCompositionText() { TextInputClient* client = GetTextInputClient(); if (client && client->HasCompositionText()) @@ -453,17 +376,13 @@ void InputMethodIBus::ResetContext() { // Note: some input method engines may not support reset method, such as // ibus-anthy. But as we control all input method engines by ourselves, we can // make sure that all of the engines we are using support it correctly. - GetInputContextClient()->Reset(); + if (GetEngine()) + GetEngine()->Reset(); character_composer_.Reset(); } void InputMethodIBus::UpdateContextFocusState() { - if (!IsContextReady()) { - context_focused_ = false; - return; - } - const bool old_context_focused = context_focused_; // Use switch here in case we are going to add more text input types. switch (GetTextInputType()) { @@ -475,19 +394,16 @@ void InputMethodIBus::UpdateContextFocusState() { context_focused_ = true; break; } + if (!GetEngine()) + return; // We only focus in |context_| when the focus is in a normal textfield. // ibus_input_context_focus_{in|out}() run asynchronously. - if (old_context_focused && !context_focused_) - GetInputContextClient()->FocusOut(); - else if (!old_context_focused && context_focused_) - GetInputContextClient()->FocusIn(); - - if (context_focused_) { - uint32 capability = kIBusCapabilityFocus | kIBusCapabilitySurroundingText; - if (CanComposeInline()) - capability |= kIBusCapabilityPreeditText; - GetInputContextClient()->SetCapabilities(capability); + if (old_context_focused && !context_focused_) { + GetEngine()->FocusOut(); + } else if (!old_context_focused && context_focused_) { + GetEngine()->FocusIn(); + OnCaretBoundsChanged(GetTextInputClient()); } } @@ -723,6 +639,13 @@ void InputMethodIBus::UpdatePreeditText(const chromeos::IBusText& text, if (suppress_next_result_ || IsTextInputTypeNone()) return; + if (!CanComposeInline()) { + chromeos::IBusPanelCandidateWindowHandlerInterface* candidate_window = + chromeos::IBusBridge::Get()->GetCandidateWindowHandler(); + if (candidate_window) + candidate_window->UpdatePreeditText(text.text(), cursor_pos, visible); + } + // |visible| argument is very confusing. For example, what's the correct // behavior when: // 1. OnUpdatePreeditText() is called with a text and visible == false, then @@ -777,71 +700,6 @@ void InputMethodIBus::DeleteSurroundingText(int32 offset, uint32 length) { GetTextInputClient()->ExtendSelectionAndDelete(length, 0U); } -void InputMethodIBus::ResetInputContext() { - context_focused_ = false; - - ConfirmCompositionText(); - - // We are dead, so we need to ask the client to stop relying on us. - OnInputMethodChanged(); - GetInputContextClient()->ResetObjectProxy(); -} - -void InputMethodIBus::CreateInputContextDone( - const dbus::ObjectPath& object_path) { - DCHECK_NE(INPUT_CONTEXT_RUNNING, input_context_state_); - - if (input_context_state_ == INPUT_CONTEXT_STOP) { - // DestroyContext has already been called. - return; - } - - chromeos::DBusThreadManager::Get()->GetIBusInputContextClient() - ->Initialize(chromeos::DBusThreadManager::Get()->GetIBusBus(), - object_path); - - input_context_state_ = INPUT_CONTEXT_RUNNING; - DCHECK(IsContextReady()); - SetUpSignalHandlers(); -} - -void InputMethodIBus::CreateInputContextFail() { - DCHECK_NE(INPUT_CONTEXT_RUNNING, input_context_state_); - if (input_context_state_ == INPUT_CONTEXT_STOP) { - // CreateInputContext failed but the input context is no longer - // necessary, thus do nothing. - return; - } - - if (++create_input_context_fail_count_ >= kMaxRetryCount) { - DVLOG(1) << "CreateInputContext failed even tried " - << kMaxRetryCount << " times, give up."; - create_input_context_fail_count_ = 0; - input_context_state_ = INPUT_CONTEXT_STOP; - return; - } - - // Try CreateInputContext again. - chromeos::DBusThreadManager::Get()->GetIBusClient()->CreateInputContext( - kClientName, - base::Bind(&InputMethodIBus::CreateInputContextDone, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&InputMethodIBus::CreateInputContextFail, - weak_ptr_factory_.GetWeakPtr())); -} - -bool InputMethodIBus::IsConnected() { - return chromeos::DBusThreadManager::Get()->GetIBusBus() != NULL; -} - -bool InputMethodIBus::IsContextReady() { - if (!IsConnected()) - return false; - if (!GetInputContextClient()) - return false; - return GetInputContextClient()->IsObjectProxyReady(); -} - bool InputMethodIBus::ExecuteCharacterComposer(uint32 ibus_keyval, uint32 ibus_keycode, uint32 ibus_state) { @@ -866,20 +724,6 @@ bool InputMethodIBus::ExecuteCharacterComposer(uint32 ibus_keyval, return consumed; } -void InputMethodIBus::OnConnected() { - DCHECK(IsConnected()); - // If already input context is initialized, do nothing. - if (IsContextReady()) - return; - - DestroyContext(); - CreateContext(); -} - -void InputMethodIBus::OnDisconnected() { - DestroyContext(); -} - void InputMethodIBus::ExtractCompositionText( const chromeos::IBusText& text, uint32 cursor_position, @@ -907,7 +751,7 @@ void InputMethodIBus::ExtractCompositionText( size_t cursor_offset = char16_offsets[std::min(char_length, cursor_position)]; - out_composition->selection = Range(cursor_offset); + out_composition->selection = gfx::Range(cursor_offset); const std::vector<chromeos::IBusText::UnderlineAttribute>& underline_attributes = text.underline_attributes(); diff --git a/chromium/ui/base/ime/input_method_ibus.h b/chromium/ui/base/ime/input_method_ibus.h index bc6aa6ec83c..3be172fdad5 100644 --- a/chromium/ui/base/ime/input_method_ibus.h +++ b/chromium/ui/base/ime/input_method_ibus.h @@ -12,8 +12,7 @@ #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" -#include "chromeos/dbus/ibus/ibus_input_context_client.h" -#include "chromeos/ime/ibus_daemon_controller.h" +#include "chromeos/ime/ibus_bridge.h" #include "ui/base/ime/character_composer.h" #include "ui/base/ime/composition_text.h" #include "ui/base/ime/input_method_base.h" @@ -32,8 +31,7 @@ namespace ui { // A ui::InputMethod implementation based on IBus. class UI_EXPORT InputMethodIBus : public InputMethodBase, - public chromeos::IBusInputContextHandlerInterface, - public chromeos::IBusDaemonController::Observer { + public chromeos::IBusInputContextHandlerInterface { public: explicit InputMethodIBus(internal::InputMethodDelegate* delegate); virtual ~InputMethodIBus(); @@ -43,7 +41,6 @@ class UI_EXPORT InputMethodIBus virtual void OnBlur() OVERRIDE; virtual bool OnUntranslatedIMEMessage(const base::NativeEvent& event, NativeEventResult* result) OVERRIDE; - virtual void Init(bool focused) OVERRIDE; virtual bool DispatchKeyEvent( const base::NativeEvent& native_key_event) OVERRIDE; virtual bool DispatchFabricatedKeyEvent(const ui::KeyEvent& event) OVERRIDE; @@ -57,10 +54,6 @@ class UI_EXPORT InputMethodIBus virtual bool IsCandidatePopupOpen() const OVERRIDE; protected: - // chromeos::IBusDaemonController::Observer overrides. - virtual void OnConnected() OVERRIDE; - virtual void OnDisconnected() OVERRIDE; - // Converts |text| into CompositionText. void ExtractCompositionText(const chromeos::IBusText& text, uint32 cursor_position, @@ -82,15 +75,6 @@ class UI_EXPORT InputMethodIBus void ResetContext(); private: - enum InputContextState { - // The input context is not working. - INPUT_CONTEXT_STOP, - // The input context is waiting for CreateInputContext reply from - // ibus-daemon. - INPUT_CONTEXT_WAIT_CREATE_INPUT_CONTEXT_RESPONSE, - // The input context is working and ready to communicate with ibus-daemon. - INPUT_CONTEXT_RUNNING, - }; class PendingKeyEvent; // Overridden from InputMethodBase: @@ -99,15 +83,6 @@ class UI_EXPORT InputMethodIBus virtual void OnDidChangeFocusedClient(TextInputClient* focused_before, TextInputClient* focused) OVERRIDE; - // Creates context asynchronously. - void CreateContext(); - - // Sets necessary signal handlers. - void SetUpSignalHandlers(); - - // Destroys context. - void DestroyContext(); - // Asks the client to confirm current composition text. void ConfirmCompositionText(); @@ -142,16 +117,6 @@ class UI_EXPORT InputMethodIBus // focus, the text input type is changed or we are destroyed. void AbandonAllPendingKeyEvents(); - // Releases context focus and confirms the composition text. Then destroy - // object proxy. - void ResetInputContext(); - - // Returns true if the connection to ibus-daemon is established. - bool IsConnected(); - - // Returns true if the input context is ready to use. - bool IsContextReady(); - // Passes keyevent and executes character composition if necessary. Returns // true if character composer comsumes key event. bool ExecuteCharacterComposer(uint32 ibus_keyval, @@ -170,8 +135,6 @@ class UI_EXPORT InputMethodIBus bool visible) OVERRIDE; virtual void DeleteSurroundingText(int32 offset, uint32 length) OVERRIDE; - void CreateInputContextDone(const dbus::ObjectPath& object_path); - void CreateInputContextFail(); void ProcessKeyEventDone(uint32 id, XEvent* xevent, uint32 ibus_keyval, uint32 ibus_keycode, uint32 ibus_state, bool is_handled); @@ -181,12 +144,6 @@ class UI_EXPORT InputMethodIBus // They will be deleted in ProcessKeyEventDone(). std::set<uint32> pending_key_events_; - // Represents input context's state. - InputContextState input_context_state_; - - // The count of CreateInputContext message failure. - int create_input_context_fail_count_; - // Pending composition text generated by the current pending key event. // It'll be sent to the focused text input client as soon as we receive the // processing result of the pending key event. @@ -198,7 +155,7 @@ class UI_EXPORT InputMethodIBus string16 result_text_; string16 previous_surrounding_text_; - ui::Range previous_selection_range_; + gfx::Range previous_selection_range_; // Indicates if input context is focused or not. bool context_focused_; @@ -220,6 +177,8 @@ class UI_EXPORT InputMethodIBus // including dead key etc. CharacterComposer character_composer_; + TextInputType previous_textinput_type_; + // Used for making callbacks. base::WeakPtrFactory<InputMethodIBus> weak_ptr_factory_; diff --git a/chromium/ui/base/ime/input_method_ibus_unittest.cc b/chromium/ui/base/ime/input_method_ibus_unittest.cc index 99accfa42c6..b88894c9418 100644 --- a/chromium/ui/base/ime/input_method_ibus_unittest.cc +++ b/chromium/ui/base/ime/input_method_ibus_unittest.cc @@ -16,9 +16,10 @@ #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/ibus/ibus_text.h" #include "chromeos/dbus/ibus/mock_ibus_client.h" -#include "chromeos/dbus/ibus/mock_ibus_input_context_client.h" #include "chromeos/dbus/mock_dbus_thread_manager_without_gmock.h" -#include "chromeos/ime/mock_ibus_daemon_controller.h" +#include "chromeos/ime/ibus_bridge.h" +#include "chromeos/ime/mock_ime_candidate_window_handler.h" +#include "chromeos/ime/mock_ime_engine_handler.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/ime/input_method_delegate.h" #include "ui/base/ime/input_method_ibus.h" @@ -38,6 +39,9 @@ const uint32 kTestIBusState1 = 99; const uint32 kTestIBusState2 = 46; const uint32 kTestIBusState3 = 8; +typedef chromeos::IBusEngineHandlerInterface::KeyEventDoneCallback + KeyEventCallback; + uint32 GetOffsetInUTF16(const std::string& utf8_string, uint32 utf8_offset) { string16 utf16_string = UTF8ToUTF16(utf8_string); DCHECK_LT(utf8_offset, utf16_string.size()); @@ -58,7 +62,6 @@ bool IsEqualXKeyEvent(const XEvent& e1, const XEvent& e2) { enum KeyEventHandlerBehavior { KEYEVENT_CONSUME, KEYEVENT_NOT_CONSUME, - KEYEVENT_ERROR, }; } // namespace @@ -149,8 +152,7 @@ class CreateInputContextSuccessHandler { } void Run(const std::string& client_name, - const chromeos::IBusClient::CreateInputContextCallback& callback, - const chromeos::IBusClient::ErrorCallback& error_callback) { + const chromeos::IBusClient::CreateInputContextCallback& callback) { EXPECT_EQ("chrome", client_name); callback.Run(object_path_); } @@ -161,25 +163,11 @@ class CreateInputContextSuccessHandler { DISALLOW_COPY_AND_ASSIGN(CreateInputContextSuccessHandler); }; -class CreateInputContextFailHandler { - public: - CreateInputContextFailHandler() {} - void Run(const std::string& client_name, - const chromeos::IBusClient::CreateInputContextCallback& callback, - const chromeos::IBusClient::ErrorCallback& error_callback) { - error_callback.Run(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(CreateInputContextFailHandler); -}; - class CreateInputContextNoResponseHandler { public: CreateInputContextNoResponseHandler() {} void Run(const std::string& client_name, - const chromeos::IBusClient::CreateInputContextCallback& callback, - const chromeos::IBusClient::ErrorCallback& error_callback) { + const chromeos::IBusClient::CreateInputContextCallback& callback) { } private: @@ -193,23 +181,17 @@ class CreateInputContextDelayHandler { } void Run(const std::string& client_name, - const chromeos::IBusClient::CreateInputContextCallback& callback, - const chromeos::IBusClient::ErrorCallback& error_callback) { + const chromeos::IBusClient::CreateInputContextCallback& callback) { callback_ = callback; - error_callback_ = error_callback; } - void RunCallback(bool success) { - if (success) - callback_.Run(object_path_); - else - error_callback_.Run(); + void RunCallback() { + callback_.Run(object_path_); } private: dbus::ObjectPath object_path_; chromeos::IBusClient::CreateInputContextCallback callback_; - chromeos::IBusClient::ErrorCallback error_callback_; DISALLOW_COPY_AND_ASSIGN(CreateInputContextDelayHandler); }; @@ -230,15 +212,11 @@ class SynchronousKeyEventHandler { void Run(uint32 keyval, uint32 keycode, uint32 state, - const IBusInputContextClient::ProcessKeyEventCallback& callback, - const IBusInputContextClient::ErrorCallback& error_callback) { + const KeyEventCallback& callback) { EXPECT_EQ(expected_keyval_, keyval); EXPECT_EQ(expected_keycode_, keycode); EXPECT_EQ(expected_state_, state); - if (behavior_ == KEYEVENT_ERROR) - error_callback.Run(); - else - callback.Run(behavior_ == KEYEVENT_CONSUME); + callback.Run(behavior_ == KEYEVENT_CONSUME); } private: @@ -264,28 +242,22 @@ class AsynchronousKeyEventHandler { void Run(uint32 keyval, uint32 keycode, uint32 state, - const IBusInputContextClient::ProcessKeyEventCallback& callback, - const IBusInputContextClient::ErrorCallback& error_callback) { + const KeyEventCallback& callback) { EXPECT_EQ(expected_keyval_, keyval); EXPECT_EQ(expected_keycode_, keycode); EXPECT_EQ(expected_state_, state); callback_ = callback; - error_callback_ = error_callback; } void RunCallback(KeyEventHandlerBehavior behavior) { - if (behavior == KEYEVENT_ERROR) - error_callback_.Run(); - else - callback_.Run(behavior == KEYEVENT_CONSUME); + callback_.Run(behavior == KEYEVENT_CONSUME); } private: const uint32 expected_keyval_; const uint32 expected_keycode_; const uint32 expected_state_; - IBusInputContextClient::ProcessKeyEventCallback callback_; - IBusInputContextClient::ErrorCallback error_callback_; + KeyEventCallback callback_; DISALLOW_COPY_AND_ASSIGN(AsynchronousKeyEventHandler); }; @@ -328,17 +300,17 @@ class InputMethodIBusTest : public internal::InputMethodDelegate, // testing::Test overrides: virtual void SetUp() OVERRIDE { - // |thread_manager_| will be released by DBusThreadManager::Shutdown - // function in TearDown function. - // Current MockIBusInputContext is strongly depend on gmock, but gmock is - // banned in ui/*. So just use stab implementation for testing. - mock_dbus_thread_manager_ = - new chromeos::MockDBusThreadManagerWithoutGMock(); - chromeos::DBusThreadManager::InitializeForTesting( - mock_dbus_thread_manager_); - mock_ibus_daemon_controller_ = new chromeos::MockIBusDaemonController(); - chromeos::IBusDaemonController::InitializeForTesting( - mock_ibus_daemon_controller_); + chromeos::IBusBridge::Initialize(); + + mock_ime_engine_handler_.reset( + new chromeos::MockIMEEngineHandler()); + chromeos::IBusBridge::Get()->SetEngineHandler( + mock_ime_engine_handler_.get()); + + mock_ime_candidate_window_handler_.reset( + new chromeos::MockIMECandidateWindowHandler()); + chromeos::IBusBridge::Get()->SetCandidateWindowHandler( + mock_ime_candidate_window_handler_.get()); ime_.reset(new TestableInputMethodIBus(this)); ime_->SetFocusedTextInputClient(this); @@ -348,18 +320,11 @@ class InputMethodIBusTest : public internal::InputMethodDelegate, if (ime_.get()) ime_->SetFocusedTextInputClient(NULL); ime_.reset(); - chromeos::DBusThreadManager::Shutdown(); - chromeos::IBusDaemonController::Shutdown(); - } - - // Helper function to initialize IBus connection for testing. - void InitIBusBus() { - mock_dbus_thread_manager_->InitIBusBus("dummy address", - base::Bind(&base::DoNothing)); - mock_ibus_client_ = mock_dbus_thread_manager_->mock_ibus_client(); - mock_ibus_input_context_client_ = - mock_dbus_thread_manager_->mock_ibus_input_context_client(); - + chromeos::IBusBridge::Get()->SetEngineHandler(NULL); + chromeos::IBusBridge::Get()->SetCandidateWindowHandler(NULL); + mock_ime_engine_handler_.reset(); + mock_ime_candidate_window_handler_.reset(); + chromeos::IBusBridge::Shutdown(); } // ui::internal::InputMethodDelegate overrides: @@ -419,19 +384,19 @@ class InputMethodIBusTest : public internal::InputMethodDelegate, CompositionText empty; return composition_text_ != empty; } - virtual bool GetTextRange(Range* range) OVERRIDE { + virtual bool GetTextRange(gfx::Range* range) OVERRIDE { *range = text_range_; return true; } - virtual bool GetCompositionTextRange(Range* range) OVERRIDE { return false; } - virtual bool GetSelectionRange(Range* range) OVERRIDE { + virtual bool GetCompositionTextRange(gfx::Range* range) OVERRIDE { return false; } + virtual bool GetSelectionRange(gfx::Range* range) OVERRIDE { *range = selection_range_; return true; } - virtual bool SetSelectionRange(const Range& range) OVERRIDE { return false; } - virtual bool DeleteRange(const Range& range) OVERRIDE { return false; } - virtual bool GetTextFromRange(const Range& range, string16* text) OVERRIDE { + virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE { return false; } + virtual bool DeleteRange(const gfx::Range& range) OVERRIDE { return false; } + virtual bool GetTextFromRange(const gfx::Range& range, string16* text) OVERRIDE { *text = surrounding_text_.substr(range.GetMin(), range.length()); return true; } @@ -471,14 +436,6 @@ class InputMethodIBusTest : public internal::InputMethodDelegate, caret_bounds_ = gfx::Rect(); } - void SetCreateContextSuccessHandler() { - CreateInputContextSuccessHandler create_input_context_handler( - dbus::ObjectPath("InputContext_1")); - mock_ibus_client_->set_create_input_context_handler(base::Bind( - &CreateInputContextSuccessHandler::Run, - base::Unretained(&create_input_context_handler))); - } - scoped_ptr<TestableInputMethodIBus> ime_; // Variables for remembering the parameters that are passed to @@ -501,15 +458,13 @@ class InputMethodIBusTest : public internal::InputMethodDelegate, TextInputType input_type_; bool can_compose_inline_; gfx::Rect caret_bounds_; - ui::Range text_range_; - ui::Range selection_range_; + gfx::Range text_range_; + gfx::Range selection_range_; string16 surrounding_text_; - // Variables for mock dbus connections. - chromeos::MockDBusThreadManagerWithoutGMock* mock_dbus_thread_manager_; - chromeos::MockIBusClient* mock_ibus_client_; - chromeos::MockIBusInputContextClient* mock_ibus_input_context_client_; - chromeos::MockIBusDaemonController* mock_ibus_daemon_controller_; + scoped_ptr<chromeos::MockIMEEngineHandler> mock_ime_engine_handler_; + scoped_ptr<chromeos::MockIMECandidateWindowHandler> + mock_ime_candidate_window_handler_; DISALLOW_COPY_AND_ASSIGN(InputMethodIBusTest); }; @@ -602,209 +557,6 @@ TEST_F(InputMethodIBusTest, GetInputTextType_WithoutFocusedWindow2) { EXPECT_EQ(TEXT_INPUT_TYPE_PASSWORD, ime_->GetTextInputType()); } -// Then, tests internal behavior of ui::InputMethodIBus, especially if the input -// method implementation calls ui::internal::IBusClient APIs as expected. - -// Start ibus-daemon first, then create ui::InputMethodIBus. Check if a new -// input context is created. -TEST_F(InputMethodIBusTest, InitiallyConnected) { - InitIBusBus(); - SetCreateContextSuccessHandler(); - ime_->Init(true); - // An input context should be created immediately since is_connected_ is true. - EXPECT_EQ(1, mock_ibus_client_->create_input_context_call_count()); - EXPECT_EQ(1, mock_ibus_input_context_client_->set_capabilities_call_count()); - // However, since the current text input type is 'NONE' (the default), FocusIn - // shouldn't be called. - EXPECT_EQ(0, mock_ibus_input_context_client_->focus_in_call_count()); - EXPECT_TRUE(mock_ibus_input_context_client_->IsObjectProxyReady()); -} - -// Create ui::InputMethodIBus, then start ibus-daemon. -TEST_F(InputMethodIBusTest, InitiallyDisconnected) { - ime_->Init(true); - // Start the daemon. - InitIBusBus(); - SetCreateContextSuccessHandler(); - mock_ibus_daemon_controller_->EmulateConnect(); - // A context should be created upon the signal delivery. - EXPECT_EQ(1, mock_ibus_client_->create_input_context_call_count()); - EXPECT_EQ(1, mock_ibus_input_context_client_->set_capabilities_call_count()); - EXPECT_EQ(0, mock_ibus_input_context_client_->focus_in_call_count()); - EXPECT_TRUE(mock_ibus_input_context_client_->IsObjectProxyReady()); -} - -// Confirm that ui::InputMethodIBus does not crash on "disconnected" signal -// delivery. -TEST_F(InputMethodIBusTest, Disconnect) { - InitIBusBus(); - SetCreateContextSuccessHandler(); - ime_->Init(true); - EXPECT_EQ(1, mock_ibus_client_->create_input_context_call_count()); - // Currently we can't shutdown IBusBus connection except in - // DBusThreadManager's shutting down. So set ibus_bus_ as NULL to emulate - // dynamical shutting down. - mock_dbus_thread_manager_->set_ibus_bus(NULL); - mock_ibus_daemon_controller_->EmulateDisconnect(); - EXPECT_FALSE(mock_ibus_input_context_client_->IsObjectProxyReady()); -} - -// Confirm that ui::InputMethodIBus re-creates an input context when ibus-daemon -// restarts. -TEST_F(InputMethodIBusTest, DisconnectThenReconnect) { - InitIBusBus(); - SetCreateContextSuccessHandler(); - ime_->Init(true); - EXPECT_EQ(1, mock_ibus_client_->create_input_context_call_count()); - EXPECT_EQ(1, mock_ibus_input_context_client_->set_capabilities_call_count()); - EXPECT_EQ(0, - mock_ibus_input_context_client_->reset_object_proxy_call_caount()); - mock_dbus_thread_manager_->set_ibus_bus(NULL); - mock_ibus_daemon_controller_->EmulateDisconnect(); - EXPECT_FALSE(mock_ibus_input_context_client_->IsObjectProxyReady()); - mock_ibus_daemon_controller_->EmulateDisconnect(); - InitIBusBus(); - SetCreateContextSuccessHandler(); - mock_ibus_daemon_controller_->EmulateConnect(); - // Check if the old context is deleted. - EXPECT_EQ(0, - mock_ibus_input_context_client_->reset_object_proxy_call_caount()); - // Check if a new context is created. - EXPECT_EQ(1, mock_ibus_client_->create_input_context_call_count()); - EXPECT_EQ(1, mock_ibus_input_context_client_->set_capabilities_call_count()); - EXPECT_TRUE(mock_ibus_input_context_client_->IsObjectProxyReady()); -} - -// Confirm that ui::InputMethodIBus does not crash even if NULL context is -// passed. -// TODO(yusukes): Currently, ui::InputMethodIBus does not try to create ic once -// it fails (unless ibus sends the "connected" signal to Chrome again). It might -// be better to add some retry logic. Will revisit later. -TEST_F(InputMethodIBusTest, CreateContextFail) { - InitIBusBus(); - CreateInputContextFailHandler create_input_context_handler; - mock_ibus_client_->set_create_input_context_handler(base::Bind( - &CreateInputContextFailHandler::Run, - base::Unretained(&create_input_context_handler))); - ime_->Init(true); - // InputMethodIBus tries several times if the CreateInputContext method call - // is failed. - EXPECT_EQ(kCreateInputContextMaxTrialCount, - mock_ibus_client_->create_input_context_call_count()); - // |set_capabilities_call_count()| should be zero since a context is not - // created yet. - EXPECT_EQ(0, mock_ibus_input_context_client_->set_capabilities_call_count()); - EXPECT_FALSE(mock_ibus_input_context_client_->IsObjectProxyReady()); -} - -// Confirm that ui::InputMethodIBus does not crash even if ibus-daemon does not -// respond. -TEST_F(InputMethodIBusTest, CreateContextNoResp) { - InitIBusBus(); - CreateInputContextNoResponseHandler create_input_context_handler; - mock_ibus_client_->set_create_input_context_handler(base::Bind( - &CreateInputContextNoResponseHandler::Run, - base::Unretained(&create_input_context_handler))); - ime_->Init(true); - EXPECT_EQ(1, mock_ibus_client_->create_input_context_call_count()); - EXPECT_EQ(0, mock_ibus_input_context_client_->set_capabilities_call_count()); - EXPECT_FALSE(mock_ibus_input_context_client_->IsObjectProxyReady()); -} - -// Confirm that ui::InputMethodIBus does not crash even if ibus-daemon responds -// after ui::InputMethodIBus is deleted. -TEST_F(InputMethodIBusTest, CreateContextFailDelayed) { - InitIBusBus(); - CreateInputContextDelayHandler create_input_context_handler( - dbus::ObjectPath("Sample object path")); - mock_ibus_client_->set_create_input_context_handler(base::Bind( - &CreateInputContextDelayHandler::Run, - base::Unretained(&create_input_context_handler))); - ime_->Init(true); - EXPECT_EQ(1, mock_ibus_client_->create_input_context_call_count()); - EXPECT_EQ(0, mock_ibus_input_context_client_->set_capabilities_call_count()); - EXPECT_FALSE(mock_ibus_input_context_client_->IsObjectProxyReady()); - - ime_->SetFocusedTextInputClient(NULL); - ime_.reset(); - EXPECT_FALSE(mock_ibus_input_context_client_->IsObjectProxyReady()); - - create_input_context_handler.RunCallback(false); - EXPECT_EQ(1, mock_ibus_client_->create_input_context_call_count()); - EXPECT_EQ(0, mock_ibus_input_context_client_->set_capabilities_call_count()); - EXPECT_FALSE(mock_ibus_input_context_client_->IsObjectProxyReady()); -} - -// Confirm that ui::InputMethodIBus does not crash even if ibus-daemon responds -// after ui::InputMethodIBus is deleted. -TEST_F(InputMethodIBusTest, CreateContextSuccessDelayed) { - InitIBusBus(); - CreateInputContextDelayHandler create_input_context_handler( - dbus::ObjectPath("Sample object path")); - mock_ibus_client_->set_create_input_context_handler(base::Bind( - &CreateInputContextDelayHandler::Run, - base::Unretained(&create_input_context_handler))); - ime_->Init(true); - EXPECT_EQ(1, mock_ibus_client_->create_input_context_call_count()); - EXPECT_EQ(0, mock_ibus_input_context_client_->set_capabilities_call_count()); - EXPECT_FALSE(mock_ibus_input_context_client_->IsObjectProxyReady()); - - ime_->SetFocusedTextInputClient(NULL); - ime_.reset(); - EXPECT_FALSE(mock_ibus_input_context_client_->IsObjectProxyReady()); - - create_input_context_handler.RunCallback(true); - EXPECT_EQ(1, mock_ibus_client_->create_input_context_call_count()); - EXPECT_EQ(0, mock_ibus_input_context_client_->set_capabilities_call_count()); - EXPECT_FALSE(mock_ibus_input_context_client_->IsObjectProxyReady()); -} - -// Confirm that ui::InputMethodIBus does not crash even if ibus-daemon responds -// after disconnected from ibus-daemon. -TEST_F(InputMethodIBusTest, CreateContextSuccessDelayedAfterDisconnection) { - InitIBusBus(); - CreateInputContextDelayHandler create_input_context_handler( - dbus::ObjectPath("Sample object path")); - mock_ibus_client_->set_create_input_context_handler(base::Bind( - &CreateInputContextDelayHandler::Run, - base::Unretained(&create_input_context_handler))); - ime_->Init(true); - EXPECT_EQ(1, mock_ibus_client_->create_input_context_call_count()); - EXPECT_EQ(0, mock_ibus_input_context_client_->set_capabilities_call_count()); - EXPECT_FALSE(mock_ibus_input_context_client_->IsObjectProxyReady()); - - mock_ibus_daemon_controller_->EmulateDisconnect(); - EXPECT_FALSE(mock_ibus_input_context_client_->IsObjectProxyReady()); - - create_input_context_handler.RunCallback(true); - EXPECT_EQ(1, mock_ibus_client_->create_input_context_call_count()); - EXPECT_EQ(0, mock_ibus_input_context_client_->set_capabilities_call_count()); - EXPECT_FALSE(mock_ibus_input_context_client_->IsObjectProxyReady()); -} - -// Confirm that ui::InputMethodIBus does not crash even if ibus-daemon responds -// after disconnected from ibus-daemon. -TEST_F(InputMethodIBusTest, CreateContextFailDelayedAfterDisconnection) { - InitIBusBus(); - CreateInputContextDelayHandler create_input_context_handler( - dbus::ObjectPath("Sample object path")); - mock_ibus_client_->set_create_input_context_handler(base::Bind( - &CreateInputContextDelayHandler::Run, - base::Unretained(&create_input_context_handler))); - ime_->Init(true); - EXPECT_EQ(1, mock_ibus_client_->create_input_context_call_count()); - EXPECT_EQ(0, mock_ibus_input_context_client_->set_capabilities_call_count()); - EXPECT_FALSE(mock_ibus_input_context_client_->IsObjectProxyReady()); - - mock_ibus_daemon_controller_->EmulateDisconnect(); - EXPECT_FALSE(mock_ibus_input_context_client_->IsObjectProxyReady()); - - create_input_context_handler.RunCallback(false); - EXPECT_EQ(1, mock_ibus_client_->create_input_context_call_count()); - EXPECT_EQ(0, mock_ibus_input_context_client_->set_capabilities_call_count()); - EXPECT_FALSE(mock_ibus_input_context_client_->IsObjectProxyReady()); -} - // Confirm that IBusClient::FocusIn is called on "connected" if input_type_ is // TEXT. TEST_F(InputMethodIBusTest, FocusIn_Text) { @@ -814,16 +566,11 @@ TEST_F(InputMethodIBusTest, FocusIn_Text) { // Click a text input form. input_type_ = TEXT_INPUT_TYPE_TEXT; ime_->OnTextInputTypeChanged(this); - // Start the daemon. - InitIBusBus(); - SetCreateContextSuccessHandler(); - mock_ibus_daemon_controller_->EmulateConnect(); - // A context should be created upon the signal delivery. - EXPECT_EQ(1, mock_ibus_client_->create_input_context_call_count()); // Since a form has focus, IBusClient::FocusIn() should be called. - EXPECT_EQ(1, mock_ibus_input_context_client_->focus_in_call_count()); - EXPECT_EQ(1, - mock_ibus_input_context_client_->set_cursor_location_call_count()); + EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count()); + EXPECT_EQ( + 1, + mock_ime_candidate_window_handler_->set_cursor_location_call_count()); // ui::TextInputClient::OnInputMethodChanged() should be called when // ui::InputMethodIBus connects/disconnects to/from ibus-daemon and the // current text input type is not NONE. @@ -837,82 +584,71 @@ TEST_F(InputMethodIBusTest, FocusIn_Password) { EXPECT_EQ(0U, on_input_method_changed_call_count_); input_type_ = TEXT_INPUT_TYPE_PASSWORD; ime_->OnTextInputTypeChanged(this); - InitIBusBus(); - SetCreateContextSuccessHandler(); - mock_ibus_daemon_controller_->EmulateConnect(); - EXPECT_EQ(1, mock_ibus_client_->create_input_context_call_count()); // Since a form has focus, IBusClient::FocusIn() should NOT be called. - EXPECT_EQ(0, mock_ibus_input_context_client_->focus_in_call_count()); + EXPECT_EQ(0, mock_ime_engine_handler_->focus_in_call_count()); EXPECT_EQ(1U, on_input_method_changed_call_count_); } // Confirm that IBusClient::FocusOut is called as expected. TEST_F(InputMethodIBusTest, FocusOut_None) { input_type_ = TEXT_INPUT_TYPE_TEXT; - InitIBusBus(); - SetCreateContextSuccessHandler(); ime_->Init(true); - EXPECT_EQ(1, mock_ibus_client_->create_input_context_call_count()); - EXPECT_EQ(1, mock_ibus_input_context_client_->focus_in_call_count()); - EXPECT_EQ(0, mock_ibus_input_context_client_->focus_out_call_count()); + EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count()); + EXPECT_EQ(0, mock_ime_engine_handler_->focus_out_call_count()); input_type_ = TEXT_INPUT_TYPE_NONE; ime_->OnTextInputTypeChanged(this); - EXPECT_EQ(1, mock_ibus_input_context_client_->focus_in_call_count()); - EXPECT_EQ(1, mock_ibus_input_context_client_->focus_out_call_count()); + EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count()); + EXPECT_EQ(1, mock_ime_engine_handler_->focus_out_call_count()); } // Confirm that IBusClient::FocusOut is called as expected. TEST_F(InputMethodIBusTest, FocusOut_Password) { input_type_ = TEXT_INPUT_TYPE_TEXT; - InitIBusBus(); - SetCreateContextSuccessHandler(); ime_->Init(true); - EXPECT_EQ(1, mock_ibus_client_->create_input_context_call_count()); - EXPECT_EQ(1, mock_ibus_input_context_client_->focus_in_call_count()); - EXPECT_EQ(0, mock_ibus_input_context_client_->focus_out_call_count()); + EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count()); + EXPECT_EQ(0, mock_ime_engine_handler_->focus_out_call_count()); input_type_ = TEXT_INPUT_TYPE_PASSWORD; ime_->OnTextInputTypeChanged(this); - EXPECT_EQ(1, mock_ibus_input_context_client_->focus_in_call_count()); - EXPECT_EQ(1, mock_ibus_input_context_client_->focus_out_call_count()); + EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count()); + EXPECT_EQ(1, mock_ime_engine_handler_->focus_out_call_count()); } // Confirm that IBusClient::FocusOut is NOT called. TEST_F(InputMethodIBusTest, FocusOut_Url) { input_type_ = TEXT_INPUT_TYPE_TEXT; - InitIBusBus(); - SetCreateContextSuccessHandler(); ime_->Init(true); - EXPECT_EQ(1, mock_ibus_client_->create_input_context_call_count()); - EXPECT_EQ(1, mock_ibus_input_context_client_->focus_in_call_count()); - EXPECT_EQ(0, mock_ibus_input_context_client_->focus_out_call_count()); + EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count()); + EXPECT_EQ(0, mock_ime_engine_handler_->focus_out_call_count()); input_type_ = TEXT_INPUT_TYPE_URL; ime_->OnTextInputTypeChanged(this); - EXPECT_EQ(1, mock_ibus_input_context_client_->focus_in_call_count()); - EXPECT_EQ(0, mock_ibus_input_context_client_->focus_out_call_count()); + EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count()); + EXPECT_EQ(0, mock_ime_engine_handler_->focus_out_call_count()); } // Test if the new |caret_bounds_| is correctly sent to ibus-daemon. TEST_F(InputMethodIBusTest, OnCaretBoundsChanged) { - InitIBusBus(); - SetCreateContextSuccessHandler(); input_type_ = TEXT_INPUT_TYPE_TEXT; ime_->Init(true); - EXPECT_EQ(0, - mock_ibus_input_context_client_->set_cursor_location_call_count()); + EXPECT_EQ( + 1, + mock_ime_candidate_window_handler_->set_cursor_location_call_count()); caret_bounds_ = gfx::Rect(1, 2, 3, 4); ime_->OnCaretBoundsChanged(this); - EXPECT_EQ(1, - mock_ibus_input_context_client_->set_cursor_location_call_count()); + EXPECT_EQ( + 2, + mock_ime_candidate_window_handler_->set_cursor_location_call_count()); caret_bounds_ = gfx::Rect(0, 2, 3, 4); ime_->OnCaretBoundsChanged(this); - EXPECT_EQ(2, - mock_ibus_input_context_client_->set_cursor_location_call_count()); + EXPECT_EQ( + 3, + mock_ime_candidate_window_handler_->set_cursor_location_call_count()); caret_bounds_ = gfx::Rect(0, 2, 3, 4); // unchanged ime_->OnCaretBoundsChanged(this); // Current InputMethodIBus implementation performs the IPC regardless of the // bounds are changed or not. - EXPECT_EQ(3, - mock_ibus_input_context_client_->set_cursor_location_call_count()); + EXPECT_EQ( + 4, + mock_ime_candidate_window_handler_->set_cursor_location_call_count()); } TEST_F(InputMethodIBusTest, ExtractCompositionTextTest_NoAttribute) { @@ -1121,28 +857,27 @@ TEST_F(InputMethodIBusTest, SurroundingText_NoSelectionTest) { // Click a text input form. input_type_ = TEXT_INPUT_TYPE_TEXT; ime_->OnTextInputTypeChanged(this); - // Start the daemon. - InitIBusBus(); - SetCreateContextSuccessHandler(); - mock_ibus_daemon_controller_->EmulateConnect(); // Set the TextInputClient behaviors. surrounding_text_ = UTF8ToUTF16("abcdef"); - text_range_ = ui::Range(0, 6); - selection_range_ = ui::Range(3, 3); + text_range_ = gfx::Range(0, 6); + selection_range_ = gfx::Range(3, 3); // Set the verifier for SetSurroundingText mock call. SetSurroundingTextVerifier verifier(UTF16ToUTF8(surrounding_text_), 3, 3); - mock_ibus_input_context_client_->set_set_surrounding_text_handler( - base::Bind(&SetSurroundingTextVerifier::Verify, - base::Unretained(&verifier))); ime_->OnCaretBoundsChanged(this); // Check the call count. EXPECT_EQ(1, - mock_ibus_input_context_client_->set_surrounding_text_call_count()); + mock_ime_engine_handler_->set_surrounding_text_call_count()); + EXPECT_EQ(UTF16ToUTF8(surrounding_text_), + mock_ime_engine_handler_->last_set_surrounding_text()); + EXPECT_EQ(3U, + mock_ime_engine_handler_->last_set_surrounding_cursor_pos()); + EXPECT_EQ(3U, + mock_ime_engine_handler_->last_set_surrounding_anchor_pos()); } TEST_F(InputMethodIBusTest, SurroundingText_SelectionTest) { @@ -1150,27 +885,26 @@ TEST_F(InputMethodIBusTest, SurroundingText_SelectionTest) { // Click a text input form. input_type_ = TEXT_INPUT_TYPE_TEXT; ime_->OnTextInputTypeChanged(this); - // Start the daemon. - InitIBusBus(); - SetCreateContextSuccessHandler(); - mock_ibus_daemon_controller_->EmulateConnect(); // Set the TextInputClient behaviors. surrounding_text_ = UTF8ToUTF16("abcdef"); - text_range_ = ui::Range(0, 6); - selection_range_ = ui::Range(2, 5); + text_range_ = gfx::Range(0, 6); + selection_range_ = gfx::Range(2, 5); // Set the verifier for SetSurroundingText mock call. SetSurroundingTextVerifier verifier(UTF16ToUTF8(surrounding_text_), 2, 5); - mock_ibus_input_context_client_->set_set_surrounding_text_handler( - base::Bind(&SetSurroundingTextVerifier::Verify, - base::Unretained(&verifier))); ime_->OnCaretBoundsChanged(this); // Check the call count. EXPECT_EQ(1, - mock_ibus_input_context_client_->set_surrounding_text_call_count()); + mock_ime_engine_handler_->set_surrounding_text_call_count()); + EXPECT_EQ(UTF16ToUTF8(surrounding_text_), + mock_ime_engine_handler_->last_set_surrounding_text()); + EXPECT_EQ(2U, + mock_ime_engine_handler_->last_set_surrounding_cursor_pos()); + EXPECT_EQ(5U, + mock_ime_engine_handler_->last_set_surrounding_anchor_pos()); } TEST_F(InputMethodIBusTest, SurroundingText_PartialText) { @@ -1178,28 +912,25 @@ TEST_F(InputMethodIBusTest, SurroundingText_PartialText) { // Click a text input form. input_type_ = TEXT_INPUT_TYPE_TEXT; ime_->OnTextInputTypeChanged(this); - // Start the daemon. - InitIBusBus(); - SetCreateContextSuccessHandler(); - mock_ibus_daemon_controller_->EmulateConnect(); // Set the TextInputClient behaviors. surrounding_text_ = UTF8ToUTF16("abcdefghij"); - text_range_ = ui::Range(5, 10); - selection_range_ = ui::Range(7, 9); - - // Set the verifier for SetSurroundingText mock call. - // Here (2, 4) is selection range in expected surrounding text coordinates. - SetSurroundingTextVerifier verifier("fghij", 2, 4); + text_range_ = gfx::Range(5, 10); + selection_range_ = gfx::Range(7, 9); - mock_ibus_input_context_client_->set_set_surrounding_text_handler( - base::Bind(&SetSurroundingTextVerifier::Verify, - base::Unretained(&verifier))); ime_->OnCaretBoundsChanged(this); // Check the call count. EXPECT_EQ(1, - mock_ibus_input_context_client_->set_surrounding_text_call_count()); + mock_ime_engine_handler_->set_surrounding_text_call_count()); + // Set the verifier for SetSurroundingText mock call. + // Here (2, 4) is selection range in expected surrounding text coordinates. + EXPECT_EQ("fghij", + mock_ime_engine_handler_->last_set_surrounding_text()); + EXPECT_EQ(2U, + mock_ime_engine_handler_->last_set_surrounding_cursor_pos()); + EXPECT_EQ(4U, + mock_ime_engine_handler_->last_set_surrounding_anchor_pos()); } TEST_F(InputMethodIBusTest, SurroundingText_BecomeEmptyText) { @@ -1207,34 +938,24 @@ TEST_F(InputMethodIBusTest, SurroundingText_BecomeEmptyText) { // Click a text input form. input_type_ = TEXT_INPUT_TYPE_TEXT; ime_->OnTextInputTypeChanged(this); - // Start the daemon. - InitIBusBus(); - SetCreateContextSuccessHandler(); - mock_ibus_daemon_controller_->EmulateConnect(); // Set the TextInputClient behaviors. // If the surrounding text becomes empty, text_range become (0, 0) and // selection range become invalid. surrounding_text_ = UTF8ToUTF16(""); - text_range_ = ui::Range(0, 0); - selection_range_ = ui::Range::InvalidRange(); - - // Set the verifier for SetSurroundingText mock call. - SetSurroundingTextVerifier verifier("", 0, 0); + text_range_ = gfx::Range(0, 0); + selection_range_ = gfx::Range::InvalidRange(); - mock_ibus_input_context_client_->set_set_surrounding_text_handler( - base::Bind(&SetSurroundingTextVerifier::Verify, - base::Unretained(&verifier))); ime_->OnCaretBoundsChanged(this); // Check the call count. EXPECT_EQ(0, - mock_ibus_input_context_client_->set_surrounding_text_call_count()); + mock_ime_engine_handler_->set_surrounding_text_call_count()); // Should not be called twice with same condition. ime_->OnCaretBoundsChanged(this); EXPECT_EQ(0, - mock_ibus_input_context_client_->set_surrounding_text_call_count()); + mock_ime_engine_handler_->set_surrounding_text_call_count()); } class InputMethodIBusKeyEventTest : public InputMethodIBusTest { @@ -1244,52 +965,13 @@ class InputMethodIBusKeyEventTest : public InputMethodIBusTest { virtual void SetUp() OVERRIDE { InputMethodIBusTest::SetUp(); - InitIBusBus(); - SetCreateContextSuccessHandler(); ime_->Init(true); - mock_ibus_daemon_controller_->EmulateConnect(); - mock_ibus_input_context_client_->SetIsXKBLayout(false); } DISALLOW_COPY_AND_ASSIGN(InputMethodIBusKeyEventTest); }; -TEST_F(InputMethodIBusKeyEventTest, KeyEventConsumeTest) { - XEvent event = {}; - event.xkey.type = KeyPress; - - // Set up IBusKeyEventFromNativeKeyEvent result. - ime_->mutable_ibus_key_event_from_native_key_event_result()->keyval - = kTestIBusKeyVal1; - ime_->mutable_ibus_key_event_from_native_key_event_result()->keycode - = kTestIBusKeyCode1; - ime_->mutable_ibus_key_event_from_native_key_event_result()->state - = kTestIBusState1; - - // Set up ProcessKeyEvent handler. - SynchronousKeyEventHandler success_consume_handler(kTestIBusKeyVal1, - kTestIBusKeyCode1, - kTestIBusState1, - KEYEVENT_CONSUME); - mock_ibus_input_context_client_->set_process_key_event_handler( - base::Bind(&SynchronousKeyEventHandler::Run, - base::Unretained(&success_consume_handler))); - - // Do key event. - input_type_ = TEXT_INPUT_TYPE_TEXT; - ime_->OnTextInputTypeChanged(this); - ime_->DispatchKeyEvent(&event); - - // Check result - EXPECT_EQ(1, - mock_ibus_input_context_client_->process_key_event_call_count()); - EXPECT_EQ(1, ime_->process_key_event_post_ime_call_count()); - EXPECT_TRUE(IsEqualXKeyEvent(event, - ime_->process_key_event_post_ime_args().event)); - EXPECT_TRUE(ime_->process_key_event_post_ime_args().handled); -} - -TEST_F(InputMethodIBusKeyEventTest, KeyEventNotConsumeTest) { +TEST_F(InputMethodIBusKeyEventTest, KeyEventDelayResponseTest) { XEvent event = {}; event.xkey.type = KeyPress; @@ -1301,82 +983,6 @@ TEST_F(InputMethodIBusKeyEventTest, KeyEventNotConsumeTest) { ime_->mutable_ibus_key_event_from_native_key_event_result()->state = kTestIBusState1; - // Set up ProcessKeyEvent handler. - SynchronousKeyEventHandler success_nonconsume_handler(kTestIBusKeyVal1, - kTestIBusKeyCode1, - kTestIBusState1, - KEYEVENT_NOT_CONSUME); - mock_ibus_input_context_client_->set_process_key_event_handler( - base::Bind(&SynchronousKeyEventHandler::Run, - base::Unretained(&success_nonconsume_handler))); - - // Do key event. - input_type_ = TEXT_INPUT_TYPE_TEXT; - ime_->OnTextInputTypeChanged(this); - ime_->DispatchKeyEvent(&event); - - EXPECT_EQ(1, - mock_ibus_input_context_client_->process_key_event_call_count()); - EXPECT_EQ(1, ime_->process_key_event_post_ime_call_count()); - EXPECT_TRUE(IsEqualXKeyEvent(event, - ime_->process_key_event_post_ime_args().event)); - EXPECT_FALSE(ime_->process_key_event_post_ime_args().handled); -} - -TEST_F(InputMethodIBusKeyEventTest, KeyEventFailTest) { - XEvent event = {}; - event.xkey.type = KeyPress; - - // Set up IBusKeyEventFromNativeKeyEvent result. - ime_->mutable_ibus_key_event_from_native_key_event_result()->keyval - = kTestIBusKeyVal1; - ime_->mutable_ibus_key_event_from_native_key_event_result()->keycode - = kTestIBusKeyCode1; - ime_->mutable_ibus_key_event_from_native_key_event_result()->state - = kTestIBusState1; - - // Set up ProcessKeyEvent handler. - SynchronousKeyEventHandler fail_handler(kTestIBusKeyVal1, - kTestIBusKeyCode1, - kTestIBusState1, - KEYEVENT_ERROR); - mock_ibus_input_context_client_->set_process_key_event_handler( - base::Bind(&SynchronousKeyEventHandler::Run, - base::Unretained(&fail_handler))); - - // Do key event. - input_type_ = TEXT_INPUT_TYPE_TEXT; - ime_->OnTextInputTypeChanged(this); - ime_->DispatchKeyEvent(&event); - - // Check result - EXPECT_EQ(1, - mock_ibus_input_context_client_->process_key_event_call_count()); - EXPECT_EQ(1, ime_->process_key_event_post_ime_call_count()); - // If some error is happend, key should not be consumed. - EXPECT_FALSE(ime_->process_key_event_post_ime_args().handled); -} - -TEST_F(InputMethodIBusKeyEventTest, KeyEventDelayResponseSuccessTest) { - XEvent event = {}; - event.xkey.type = KeyPress; - - // Set up IBusKeyEventFromNativeKeyEvent result. - ime_->mutable_ibus_key_event_from_native_key_event_result()->keyval - = kTestIBusKeyVal1; - ime_->mutable_ibus_key_event_from_native_key_event_result()->keycode - = kTestIBusKeyCode1; - ime_->mutable_ibus_key_event_from_native_key_event_result()->state - = kTestIBusState1; - - // Set up ProcessKeyEvent handler. - AsynchronousKeyEventHandler success_consume_handler(kTestIBusKeyVal1, - kTestIBusKeyCode1, - kTestIBusState1); - mock_ibus_input_context_client_->set_process_key_event_handler( - base::Bind(&AsynchronousKeyEventHandler::Run, - base::Unretained(&success_consume_handler))); - // Do key event. input_type_ = TEXT_INPUT_TYPE_TEXT; ime_->OnTextInputTypeChanged(this); @@ -1384,11 +990,17 @@ TEST_F(InputMethodIBusKeyEventTest, KeyEventDelayResponseSuccessTest) { // Check before state. EXPECT_EQ(1, - mock_ibus_input_context_client_->process_key_event_call_count()); + mock_ime_engine_handler_->process_key_event_call_count()); + EXPECT_EQ(kTestIBusKeyVal1, + mock_ime_engine_handler_->last_processed_keysym()); + EXPECT_EQ(kTestIBusKeyCode1, + mock_ime_engine_handler_->last_processed_keycode()); + EXPECT_EQ(kTestIBusState1, + mock_ime_engine_handler_->last_processed_state()); EXPECT_EQ(0, ime_->process_key_event_post_ime_call_count()); // Do callback. - success_consume_handler.RunCallback(KEYEVENT_CONSUME); + mock_ime_engine_handler_->last_passed_callback().Run(true); // Check the results EXPECT_EQ(1, ime_->process_key_event_post_ime_call_count()); @@ -1397,46 +1009,7 @@ TEST_F(InputMethodIBusKeyEventTest, KeyEventDelayResponseSuccessTest) { EXPECT_TRUE(ime_->process_key_event_post_ime_args().handled); } -TEST_F(InputMethodIBusKeyEventTest, KeyEventDelayResponseFailTest) { - XEvent event = {}; - event.xkey.type = KeyPress; - - // Set up IBusKeyEventFromNativeKeyEvent result. - ime_->mutable_ibus_key_event_from_native_key_event_result()->keyval - = kTestIBusKeyVal1; - ime_->mutable_ibus_key_event_from_native_key_event_result()->keycode - = kTestIBusKeyCode1; - ime_->mutable_ibus_key_event_from_native_key_event_result()->state - = kTestIBusState1; - - // Set up ProcessKeyEvent handler. - AsynchronousKeyEventHandler fail_handler(kTestIBusKeyVal1, kTestIBusKeyCode1, - kTestIBusState1); - mock_ibus_input_context_client_->set_process_key_event_handler( - base::Bind(&AsynchronousKeyEventHandler::Run, - base::Unretained(&fail_handler))); - - // Do key event. - input_type_ = TEXT_INPUT_TYPE_TEXT; - ime_->OnTextInputTypeChanged(this); - ime_->DispatchKeyEvent(&event); - - // Check before state. - EXPECT_EQ(1, - mock_ibus_input_context_client_->process_key_event_call_count()); - EXPECT_EQ(0, ime_->process_key_event_post_ime_call_count()); - - // Do callback. - fail_handler.RunCallback(KEYEVENT_ERROR); - - // Check the results - EXPECT_EQ(1, ime_->process_key_event_post_ime_call_count()); - EXPECT_TRUE(IsEqualXKeyEvent(event, - ime_->process_key_event_post_ime_args().event)); - EXPECT_FALSE(ime_->process_key_event_post_ime_args().handled); -} - -TEST_F(InputMethodIBusKeyEventTest, MultiKeyEventDelayResponseSuccessTest) { +TEST_F(InputMethodIBusKeyEventTest, MultiKeyEventDelayResponseTest) { // Preparation input_type_ = TEXT_INPUT_TYPE_TEXT; ime_->OnTextInputTypeChanged(this); @@ -1452,83 +1025,17 @@ TEST_F(InputMethodIBusKeyEventTest, MultiKeyEventDelayResponseSuccessTest) { ime_->mutable_ibus_key_event_from_native_key_event_result()->state = kTestIBusState1; - // Set up ProcessKeyEvent handler. - AsynchronousKeyEventHandler handler1(kTestIBusKeyVal1, kTestIBusKeyCode1, - kTestIBusState1); - mock_ibus_input_context_client_->set_process_key_event_handler( - base::Bind(&AsynchronousKeyEventHandler::Run, - base::Unretained(&handler1))); - // Do key event. ime_->DispatchKeyEvent(&event); + EXPECT_EQ(kTestIBusKeyVal1, + mock_ime_engine_handler_->last_processed_keysym()); + EXPECT_EQ(kTestIBusKeyCode1, + mock_ime_engine_handler_->last_processed_keycode()); + EXPECT_EQ(kTestIBusState1, + mock_ime_engine_handler_->last_processed_state()); - // Set up IBusKeyEventFromNativeKeyEvent result for second key event. - ime_->mutable_ibus_key_event_from_native_key_event_result()->keyval - = kTestIBusKeyVal2; - ime_->mutable_ibus_key_event_from_native_key_event_result()->keycode - = kTestIBusKeyCode2; - ime_->mutable_ibus_key_event_from_native_key_event_result()->state - = kTestIBusState2; - - // Set up yet another ProcessKeyEvent handler. - AsynchronousKeyEventHandler handler2(kTestIBusKeyVal2, kTestIBusKeyCode2, - kTestIBusState2); - mock_ibus_input_context_client_->set_process_key_event_handler( - base::Bind(&AsynchronousKeyEventHandler::Run, - base::Unretained(&handler2))); - - // Do key event again. - ime_->DispatchKeyEvent(&event); - - // Check before state. - EXPECT_EQ(2, - mock_ibus_input_context_client_->process_key_event_call_count()); - EXPECT_EQ(0, ime_->process_key_event_post_ime_call_count()); - - // Do callback for first key event. - handler1.RunCallback(KEYEVENT_CONSUME); - - // Check the results for first key event. - EXPECT_EQ(1, ime_->process_key_event_post_ime_call_count()); - EXPECT_TRUE(IsEqualXKeyEvent(event, - ime_->process_key_event_post_ime_args().event)); - EXPECT_TRUE(ime_->process_key_event_post_ime_args().handled); - - // Do callback for second key event. - handler2.RunCallback(KEYEVENT_NOT_CONSUME); - - // Check the results for second key event. - EXPECT_EQ(2, ime_->process_key_event_post_ime_call_count()); - EXPECT_TRUE(IsEqualXKeyEvent(event, - ime_->process_key_event_post_ime_args().event)); - EXPECT_FALSE(ime_->process_key_event_post_ime_args().handled); -} - -TEST_F(InputMethodIBusKeyEventTest, MultiKeyEventDelayResponseFailTest) { - // Preparation - input_type_ = TEXT_INPUT_TYPE_TEXT; - ime_->OnTextInputTypeChanged(this); - - XEvent event = {}; - event.xkey.type = KeyPress; - - // Set up IBusKeyEventFromNativeKeyEvent result for first key event. - ime_->mutable_ibus_key_event_from_native_key_event_result()->keyval - = kTestIBusKeyVal1; - ime_->mutable_ibus_key_event_from_native_key_event_result()->keycode - = kTestIBusKeyCode1; - ime_->mutable_ibus_key_event_from_native_key_event_result()->state - = kTestIBusState1; - - // Set up ProcessKeyEvent handler. - AsynchronousKeyEventHandler handler1(kTestIBusKeyVal1, kTestIBusKeyCode1, - kTestIBusState1); - mock_ibus_input_context_client_->set_process_key_event_handler( - base::Bind(&AsynchronousKeyEventHandler::Run, - base::Unretained(&handler1))); - - // Do key event. - ime_->DispatchKeyEvent(&event); + KeyEventCallback first_callback = + mock_ime_engine_handler_->last_passed_callback(); // Set up IBusKeyEventFromNativeKeyEvent result for second key event. ime_->mutable_ibus_key_event_from_native_key_event_result()->keyval @@ -1538,110 +1045,22 @@ TEST_F(InputMethodIBusKeyEventTest, MultiKeyEventDelayResponseFailTest) { ime_->mutable_ibus_key_event_from_native_key_event_result()->state = kTestIBusState2; - // Set up yet another ProcessKeyEvent handler. - AsynchronousKeyEventHandler handler2(kTestIBusKeyVal2, kTestIBusKeyCode2, - kTestIBusState2); - mock_ibus_input_context_client_->set_process_key_event_handler( - base::Bind(&AsynchronousKeyEventHandler::Run, - base::Unretained(&handler2))); - // Do key event again. ime_->DispatchKeyEvent(&event); + EXPECT_EQ(kTestIBusKeyVal2, + mock_ime_engine_handler_->last_processed_keysym()); + EXPECT_EQ(kTestIBusKeyCode2, + mock_ime_engine_handler_->last_processed_keycode()); + EXPECT_EQ(kTestIBusState2, + mock_ime_engine_handler_->last_processed_state()); // Check before state. EXPECT_EQ(2, - mock_ibus_input_context_client_->process_key_event_call_count()); - EXPECT_EQ(0, ime_->process_key_event_post_ime_call_count()); - - // Do callback for first key event. - handler1.RunCallback(KEYEVENT_ERROR); - - // Check the results for first key event. - EXPECT_EQ(1, ime_->process_key_event_post_ime_call_count()); - EXPECT_TRUE(IsEqualXKeyEvent(event, - ime_->process_key_event_post_ime_args().event)); - EXPECT_FALSE(ime_->process_key_event_post_ime_args().handled); - - // Do callback for second key event. - handler2.RunCallback(KEYEVENT_ERROR); - - // Check the results for second key event. - EXPECT_EQ(2, ime_->process_key_event_post_ime_call_count()); - EXPECT_TRUE(IsEqualXKeyEvent(event, - ime_->process_key_event_post_ime_args().event)); - EXPECT_FALSE(ime_->process_key_event_post_ime_args().handled); -} - -TEST_F(InputMethodIBusKeyEventTest, - MultiKeyEventDelayResponseSuccessFailMixTest) { - // Preparation - input_type_ = TEXT_INPUT_TYPE_TEXT; - ime_->OnTextInputTypeChanged(this); - - XEvent event = {}; - event.xkey.type = KeyPress; - - // Set up IBusKeyEventFromNativeKeyEvent result for first key event. - ime_->mutable_ibus_key_event_from_native_key_event_result()->keyval - = kTestIBusKeyVal1; - ime_->mutable_ibus_key_event_from_native_key_event_result()->keycode - = kTestIBusKeyCode1; - ime_->mutable_ibus_key_event_from_native_key_event_result()->state - = kTestIBusState1; - - // Set up ProcessKeyEvent handler. - AsynchronousKeyEventHandler handler1(kTestIBusKeyVal1, kTestIBusKeyCode1, - kTestIBusState1); - mock_ibus_input_context_client_->set_process_key_event_handler( - base::Bind(&AsynchronousKeyEventHandler::Run, - base::Unretained(&handler1))); - - // Do key event. - ime_->DispatchKeyEvent(&event); - - // Set up IBusKeyEventFromNativeKeyEvent result for second key event. - ime_->mutable_ibus_key_event_from_native_key_event_result()->keyval - = kTestIBusKeyVal2; - ime_->mutable_ibus_key_event_from_native_key_event_result()->keycode - = kTestIBusKeyCode2; - ime_->mutable_ibus_key_event_from_native_key_event_result()->state - = kTestIBusState2; - - // Set up yet another ProcessKeyEvent handler. - AsynchronousKeyEventHandler handler2(kTestIBusKeyVal2, kTestIBusKeyCode2, - kTestIBusState2); - mock_ibus_input_context_client_->set_process_key_event_handler( - base::Bind(&AsynchronousKeyEventHandler::Run, - base::Unretained(&handler2))); - - // Do key event again. - ime_->DispatchKeyEvent(&event); - - // Set up IBusKeyEventFromNativeKeyEvent result for second key event. - ime_->mutable_ibus_key_event_from_native_key_event_result()->keyval - = kTestIBusKeyVal3; - ime_->mutable_ibus_key_event_from_native_key_event_result()->keycode - = kTestIBusKeyCode3; - ime_->mutable_ibus_key_event_from_native_key_event_result()->state - = kTestIBusState3; - - // Set up yet another ProcessKeyEvent handler. - AsynchronousKeyEventHandler handler3(kTestIBusKeyVal3, kTestIBusKeyCode3, - kTestIBusState3); - mock_ibus_input_context_client_->set_process_key_event_handler( - base::Bind(&AsynchronousKeyEventHandler::Run, - base::Unretained(&handler3))); - - // Do key event again. - ime_->DispatchKeyEvent(&event); - - // Check before state. - EXPECT_EQ(3, - mock_ibus_input_context_client_->process_key_event_call_count()); + mock_ime_engine_handler_->process_key_event_call_count()); EXPECT_EQ(0, ime_->process_key_event_post_ime_call_count()); // Do callback for first key event. - handler1.RunCallback(KEYEVENT_CONSUME); + first_callback.Run(true); // Check the results for first key event. EXPECT_EQ(1, ime_->process_key_event_post_ime_call_count()); @@ -1650,22 +1069,13 @@ TEST_F(InputMethodIBusKeyEventTest, EXPECT_TRUE(ime_->process_key_event_post_ime_args().handled); // Do callback for second key event. - handler2.RunCallback(KEYEVENT_ERROR); + mock_ime_engine_handler_->last_passed_callback().Run(false); // Check the results for second key event. EXPECT_EQ(2, ime_->process_key_event_post_ime_call_count()); EXPECT_TRUE(IsEqualXKeyEvent(event, ime_->process_key_event_post_ime_args().event)); EXPECT_FALSE(ime_->process_key_event_post_ime_args().handled); - - // Do callback for first key event. - handler3.RunCallback(KEYEVENT_CONSUME); - - // Check the results for first key event. - EXPECT_EQ(3, ime_->process_key_event_post_ime_call_count()); - EXPECT_TRUE(IsEqualXKeyEvent(event, - ime_->process_key_event_post_ime_args().event)); - EXPECT_TRUE(ime_->process_key_event_post_ime_args().handled); } TEST_F(InputMethodIBusKeyEventTest, KeyEventDelayResponseResetTest) { @@ -1680,14 +1090,6 @@ TEST_F(InputMethodIBusKeyEventTest, KeyEventDelayResponseResetTest) { ime_->mutable_ibus_key_event_from_native_key_event_result()->state = kTestIBusState1; - // Set up ProcessKeyEvent handler. - AsynchronousKeyEventHandler success_consume_handler(kTestIBusKeyVal1, - kTestIBusKeyCode1, - kTestIBusState1); - mock_ibus_input_context_client_->set_process_key_event_handler( - base::Bind(&AsynchronousKeyEventHandler::Run, - base::Unretained(&success_consume_handler))); - // Do key event. input_type_ = TEXT_INPUT_TYPE_TEXT; ime_->OnTextInputTypeChanged(this); @@ -1695,13 +1097,13 @@ TEST_F(InputMethodIBusKeyEventTest, KeyEventDelayResponseResetTest) { // Check before state. EXPECT_EQ(1, - mock_ibus_input_context_client_->process_key_event_call_count()); + mock_ime_engine_handler_->process_key_event_call_count()); EXPECT_EQ(0, ime_->process_key_event_post_ime_call_count()); ime_->ResetContext(); // Do callback. - success_consume_handler.RunCallback(KEYEVENT_CONSUME); + mock_ime_engine_handler_->last_passed_callback().Run(true); EXPECT_EQ(0, ime_->process_key_event_post_ime_call_count()); } diff --git a/chromium/ui/base/ime/input_method_imm32.cc b/chromium/ui/base/ime/input_method_imm32.cc index 1a3cf266afe..41f65dfb37d 100644 --- a/chromium/ui/base/ime/input_method_imm32.cc +++ b/chromium/ui/base/ime/input_method_imm32.cc @@ -120,11 +120,6 @@ void InputMethodIMM32::CancelComposition(const TextInputClient* client) { imm32_manager_.CancelIME(GetAttachedWindowHandle(client)); } -void InputMethodIMM32::SetFocusedTextInputClient(TextInputClient* client) { - ConfirmCompositionText(); - InputMethodWin::SetFocusedTextInputClient(client); -} - bool InputMethodIMM32::IsCandidatePopupOpen() const { return is_candidate_popup_open_; } @@ -158,8 +153,7 @@ LRESULT InputMethodIMM32::OnImeSetContext(HWND window_handle, WPARAM wparam, LPARAM lparam, BOOL* handled) { - active_ = (wparam == TRUE); - if (active_) + if (!!wparam) imm32_manager_.CreateImeWindow(window_handle); OnInputMethodChanged(); @@ -270,24 +264,20 @@ void InputMethodIMM32::ConfirmCompositionText() { void InputMethodIMM32::UpdateIMEState() { // Use switch here in case we are going to add more text input types. // We disable input method in password field. + const HWND window_handle = GetAttachedWindowHandle(GetTextInputClient()); switch (GetTextInputType()) { case ui::TEXT_INPUT_TYPE_NONE: case ui::TEXT_INPUT_TYPE_PASSWORD: - imm32_manager_.DisableIME(GetAttachedWindowHandle(GetTextInputClient())); + imm32_manager_.DisableIME(window_handle); enabled_ = false; break; default: - imm32_manager_.EnableIME(GetAttachedWindowHandle(GetTextInputClient())); + imm32_manager_.EnableIME(window_handle); enabled_ = true; break; } -} -bool InputMethodIMM32::IsWindowFocused(const TextInputClient* client) const { - if (!client) - return false; - HWND attached_window_handle = GetAttachedWindowHandle(client); - return attached_window_handle && GetFocus() == attached_window_handle; + imm32_manager_.SetTextInputMode(window_handle, GetTextInputMode()); } } // namespace ui diff --git a/chromium/ui/base/ime/input_method_imm32.h b/chromium/ui/base/ime/input_method_imm32.h index a67d79681ce..dc0a4dc8ea6 100644 --- a/chromium/ui/base/ime/input_method_imm32.h +++ b/chromium/ui/base/ime/input_method_imm32.h @@ -29,7 +29,6 @@ class UI_EXPORT InputMethodIMM32 : public InputMethodWin { virtual void OnTextInputTypeChanged(const TextInputClient* client) OVERRIDE; virtual void OnCaretBoundsChanged(const TextInputClient* client) OVERRIDE; virtual void CancelComposition(const TextInputClient* client) OVERRIDE; - virtual void SetFocusedTextInputClient(TextInputClient* client) OVERRIDE; virtual bool IsCandidatePopupOpen() const OVERRIDE; protected: @@ -71,10 +70,6 @@ class UI_EXPORT InputMethodIMM32 : public InputMethodWin { // Enables or disables the IME according to the current text input type. void UpdateIMEState(); - // Returns true if the Win32 native window bound to |client| has Win32 input - // focus. - bool IsWindowFocused(const TextInputClient* client) const; - bool enabled_; // True if we know for sure that a candidate window is open. diff --git a/chromium/ui/base/ime/input_method_initializer.cc b/chromium/ui/base/ime/input_method_initializer.cc index 69b76d6e067..8c4d34fee91 100644 --- a/chromium/ui/base/ime/input_method_initializer.cc +++ b/chromium/ui/base/ime/input_method_initializer.cc @@ -10,7 +10,7 @@ #include "base/chromeos/chromeos_version.h" #include "base/logging.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/ime/ibus_daemon_controller.h" +#include "chromeos/ime/ibus_bridge.h" #elif defined(OS_WIN) #include "base/win/metro.h" #include "ui/base/ime/win/tsf_bridge.h" @@ -25,14 +25,18 @@ bool dbus_thread_manager_was_initialized = false; namespace ui { void InitializeInputMethod() { -#if defined(OS_WIN) +#if defined(OS_CHROMEOS) + chromeos::IBusBridge::Initialize(); +#elif defined(OS_WIN) if (base::win::IsTSFAwareRequired()) ui::TSFBridge::Initialize(); #endif } void ShutdownInputMethod() { -#if defined(OS_WIN) +#if defined(OS_CHROMEOS) + chromeos::IBusBridge::Shutdown(); +#elif defined(OS_WIN) ui::internal::DestroySharedInputMethod(); if (base::win::IsTSFAwareRequired()) ui::TSFBridge::Shutdown(); @@ -41,16 +45,12 @@ void ShutdownInputMethod() { void InitializeInputMethodForTesting() { #if defined(OS_CHROMEOS) + chromeos::IBusBridge::Initialize(); + // TODO(nona): Remove DBusThreadManager initialize. if (!chromeos::DBusThreadManager::IsInitialized()) { chromeos::DBusThreadManager::InitializeWithStub(); dbus_thread_manager_was_initialized = true; } - if (!chromeos::IBusDaemonController::GetInstance()) { - // Passing NULL is okay because IBusDaemonController will be initialized - // with stub implementation on non-ChromeOS device. - DCHECK(!base::chromeos::IsRunningOnChromeOS()); - chromeos::IBusDaemonController::Initialize(NULL, NULL); - } #elif defined(OS_WIN) if (base::win::IsTSFAwareRequired()) { // Make sure COM is initialized because TSF depends on COM. @@ -62,12 +62,12 @@ void InitializeInputMethodForTesting() { void ShutdownInputMethodForTesting() { #if defined(OS_CHROMEOS) + chromeos::IBusBridge::Shutdown(); + // TODO(nona): Remove DBusThreadManager finalize. if (dbus_thread_manager_was_initialized) { chromeos::DBusThreadManager::Shutdown(); dbus_thread_manager_was_initialized = false; } - if (chromeos::IBusDaemonController::GetInstance()) - chromeos::IBusDaemonController::Shutdown(); #elif defined(OS_WIN) ui::internal::DestroySharedInputMethod(); if (base::win::IsTSFAwareRequired()) { diff --git a/chromium/ui/base/ime/input_method_tsf.cc b/chromium/ui/base/ime/input_method_tsf.cc index 21a57a86e17..aaec2e01f83 100644 --- a/chromium/ui/base/ime/input_method_tsf.cc +++ b/chromium/ui/base/ime/input_method_tsf.cc @@ -115,17 +115,9 @@ void InputMethodTSF::CancelComposition(const TextInputClient* client) { ui::TSFBridge::GetInstance()->CancelComposition(); } -void InputMethodTSF::SetFocusedTextInputClient(TextInputClient* client) { - if (IsWindowFocused(client)) { - ui::TSFBridge::GetInstance()->SetFocusedClient( - GetAttachedWindowHandle(client), client); - } else if (!client) { - // SetFocusedTextInputClient(NULL) must be interpreted as - // "Remove the attached client". - ui::TSFBridge::GetInstance()->RemoveFocusedClient( - ui::TSFBridge::GetInstance()->GetFocusedTextInputClient()); - } - InputMethodWin::SetFocusedTextInputClient(client); +void InputMethodTSF::DetachTextInputClient(TextInputClient* client) { + InputMethodWin::DetachTextInputClient(client); + ui::TSFBridge::GetInstance()->RemoveFocusedClient(client); } bool InputMethodTSF::IsCandidatePopupOpen() const { @@ -142,9 +134,10 @@ void InputMethodTSF::OnWillChangeFocusedClient(TextInputClient* focused_before, void InputMethodTSF::OnDidChangeFocusedClient(TextInputClient* focused_before, TextInputClient* focused) { - if (IsWindowFocused(focused)) { + if (IsWindowFocused(focused) && IsTextInputClientFocused(focused)) { ui::TSFBridge::GetInstance()->SetFocusedClient( GetAttachedWindowHandle(focused), focused); + // Force to update the input type since client's TextInputStateChanged() // function might not be called if text input types before the client loses // focus and after it acquires focus again are the same. @@ -161,11 +154,4 @@ void InputMethodTSF::ConfirmCompositionText() { ui::TSFBridge::GetInstance()->ConfirmComposition(); } -bool InputMethodTSF::IsWindowFocused(const TextInputClient* client) const { - if (!client) - return false; - HWND attached_window_handle = GetAttachedWindowHandle(client); - return attached_window_handle && GetFocus() == attached_window_handle; -} - } // namespace ui diff --git a/chromium/ui/base/ime/input_method_tsf.h b/chromium/ui/base/ime/input_method_tsf.h index 98fa1f738c8..2b4a9bde10c 100644 --- a/chromium/ui/base/ime/input_method_tsf.h +++ b/chromium/ui/base/ime/input_method_tsf.h @@ -31,7 +31,7 @@ class UI_EXPORT InputMethodTSF : public InputMethodWin { virtual void OnTextInputTypeChanged(const TextInputClient* client) OVERRIDE; virtual void OnCaretBoundsChanged(const TextInputClient* client) OVERRIDE; virtual void CancelComposition(const TextInputClient* client) OVERRIDE; - virtual void SetFocusedTextInputClient(TextInputClient* client) OVERRIDE; + virtual void DetachTextInputClient(TextInputClient* client) OVERRIDE; virtual bool IsCandidatePopupOpen() const OVERRIDE; // Overridden from InputMethodBase: @@ -46,10 +46,6 @@ class UI_EXPORT InputMethodTSF : public InputMethodWin { // Asks the client to confirm current composition text. void ConfirmCompositionText(); - // Returns true if the Win32 native window bound to |client| has Win32 input - // focus. - bool IsWindowFocused(const TextInputClient* client) const; - // TSF event router and observer. scoped_ptr<TSFEventObserver> tsf_event_observer_; scoped_ptr<TSFEventRouter> tsf_event_router_; diff --git a/chromium/ui/base/ime/input_method_win.cc b/chromium/ui/base/ime/input_method_win.cc index 4e3df395de4..bf679ed928b 100644 --- a/chromium/ui/base/ime/input_method_win.cc +++ b/chromium/ui/base/ime/input_method_win.cc @@ -5,12 +5,12 @@ #include "ui/base/ime/input_method_win.h" #include "base/basictypes.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/events/event_utils.h" #include "ui/base/ime/text_input_client.h" -#include "ui/base/keycodes/keyboard_codes.h" -#include "ui/base/win/hwnd_util.h" +#include "ui/events/event.h" +#include "ui/events/event_constants.h" +#include "ui/events/event_utils.h" +#include "ui/events/keycodes/keyboard_codes.h" +#include "ui/gfx/win/hwnd_util.h" namespace ui { namespace { @@ -148,13 +148,17 @@ LRESULT InputMethodWin::OnChar(HWND window_handle, if (GetTextInputClient()) { GetTextInputClient()->InsertChar(static_cast<char16>(wparam), ui::GetModifiersFromKeyState()); + + // If Windows sends a WM_CHAR, then any previously sent WM_DEADCHARs (which + // are displayed as the composition text) should be cleared. + GetTextInputClient()->ClearCompositionText(); } // Explicitly show the system menu at a good location on [Alt]+[Space]. // Note: Setting |handled| to FALSE for DefWindowProc triggering of the system // menu causes undesirable titlebar artifacts in the classic theme. if (message == WM_SYSCHAR && wparam == VK_SPACE) - ui::ShowSystemMenu(window_handle); + gfx::ShowSystemMenu(window_handle); return 0; } @@ -175,7 +179,7 @@ LRESULT InputMethodWin::OnDeadChar(UINT message, // what dead key was pressed. ui::CompositionText composition; composition.text.assign(1, static_cast<char16>(wparam)); - composition.selection = ui::Range(0, 1); + composition.selection = gfx::Range(0, 1); composition.underlines.push_back( ui::CompositionUnderline(0, 1, SK_ColorBLACK, false)); GetTextInputClient()->SetCompositionText(composition); @@ -187,12 +191,12 @@ LRESULT InputMethodWin::OnDocumentFeed(RECONVERTSTRING* reconv) { if (!client) return 0; - ui::Range text_range; + gfx::Range text_range; if (!client->GetTextRange(&text_range) || text_range.is_empty()) return 0; bool result = false; - ui::Range target_range; + gfx::Range target_range; if (client->HasCompositionText()) result = client->GetCompositionTextRange(&target_range); @@ -254,11 +258,11 @@ LRESULT InputMethodWin::OnReconvertString(RECONVERTSTRING* reconv) { if (client->HasCompositionText()) return 0; - ui::Range text_range; + gfx::Range text_range; if (!client->GetTextRange(&text_range) || text_range.is_empty()) return 0; - ui::Range selection_range; + gfx::Range selection_range; if (!client->GetSelectionRange(&selection_range) || selection_range.is_empty()) { return 0; @@ -347,4 +351,20 @@ HWND InputMethodWin::GetAttachedWindowHandle( #endif } +bool InputMethodWin::IsWindowFocused(const TextInputClient* client) const { + if (!client) + return false; + HWND attached_window_handle = GetAttachedWindowHandle(client); +#if defined(USE_AURA) + // When Aura is enabled, |attached_window_handle| should always be a top-level + // window. So we can safely assume that |attached_window_handle| is ready for + // receiving keyboard input as long as it is an active window. This works well + // even when the |attached_window_handle| becomes active but has not received + // WM_FOCUS yet. + return attached_window_handle && GetActiveWindow() == attached_window_handle; +#else + return attached_window_handle && GetFocus() == attached_window_handle; +#endif +} + } // namespace ui diff --git a/chromium/ui/base/ime/input_method_win.h b/chromium/ui/base/ime/input_method_win.h index 4d627e422f2..c69f2db6025 100644 --- a/chromium/ui/base/ime/input_method_win.h +++ b/chromium/ui/base/ime/input_method_win.h @@ -57,6 +57,10 @@ class UI_EXPORT InputMethodWin : public InputMethodBase { // On Aura environment, |toplevel_window_handle_| is always returned. HWND GetAttachedWindowHandle(const TextInputClient* text_input_client) const; + // Returns true if the Win32 native window bound to |client| is considered + // to be ready for receiving keyboard input. + bool IsWindowFocused(const TextInputClient* client) const; + // Indicates if the current input locale has an IME. bool active_; diff --git a/chromium/ui/base/ime/mock_input_method.cc b/chromium/ui/base/ime/mock_input_method.cc index 7701b5c8f01..b6323ef1821 100644 --- a/chromium/ui/base/ime/mock_input_method.cc +++ b/chromium/ui/base/ime/mock_input_method.cc @@ -7,7 +7,8 @@ namespace ui { MockInputMethod::MockInputMethod(internal::InputMethodDelegate* delegate) - : text_input_client_(NULL) { + : text_input_client_(NULL), + is_sticky_text_input_client_(false) { } MockInputMethod::~MockInputMethod() { @@ -17,6 +18,17 @@ void MockInputMethod::SetDelegate(internal::InputMethodDelegate* delegate) { } void MockInputMethod::SetFocusedTextInputClient(TextInputClient* client) { + if (is_sticky_text_input_client_) + return; + if (text_input_client_ == client) + return; + text_input_client_ = client; + if (client) + OnTextInputTypeChanged(client); +} + +void MockInputMethod::SetStickyFocusedTextInputClient(TextInputClient* client) { + is_sticky_text_input_client_ = (client != NULL); if (text_input_client_ == client) return; text_input_client_ = client; @@ -24,6 +36,13 @@ void MockInputMethod::SetFocusedTextInputClient(TextInputClient* client) { OnTextInputTypeChanged(client); } +void MockInputMethod::DetachTextInputClient(TextInputClient* client) { + if (text_input_client_ == client) { + text_input_client_ = NULL; + is_sticky_text_input_client_ = false; + } +} + TextInputClient* MockInputMethod::GetTextInputClient() const { return text_input_client_; } @@ -83,8 +102,12 @@ bool MockInputMethod::IsActive() { return true; } -ui::TextInputType MockInputMethod::GetTextInputType() const { - return ui::TEXT_INPUT_TYPE_NONE; +TextInputType MockInputMethod::GetTextInputType() const { + return TEXT_INPUT_TYPE_NONE; +} + +TextInputMode MockInputMethod::GetTextInputMode() const { + return TEXT_INPUT_MODE_DEFAULT; } bool MockInputMethod::CanComposeInline() const { diff --git a/chromium/ui/base/ime/mock_input_method.h b/chromium/ui/base/ime/mock_input_method.h index f318ca40ff4..8e14988ef5b 100644 --- a/chromium/ui/base/ime/mock_input_method.h +++ b/chromium/ui/base/ime/mock_input_method.h @@ -49,6 +49,9 @@ class UI_EXPORT MockInputMethod : NON_EXPORTED_BASE(public InputMethod) { virtual bool OnUntranslatedIMEMessage(const base::NativeEvent& event, NativeEventResult* result) OVERRIDE; virtual void SetFocusedTextInputClient(TextInputClient* client) OVERRIDE; + virtual void SetStickyFocusedTextInputClient( + TextInputClient* client) OVERRIDE; + virtual void DetachTextInputClient(TextInputClient* client) OVERRIDE; virtual TextInputClient* GetTextInputClient() const OVERRIDE; virtual bool DispatchKeyEvent(const base::NativeEvent& native_event) OVERRIDE; virtual bool DispatchFabricatedKeyEvent(const ui::KeyEvent& event) OVERRIDE; @@ -60,6 +63,7 @@ class UI_EXPORT MockInputMethod : NON_EXPORTED_BASE(public InputMethod) { virtual base::i18n::TextDirection GetInputTextDirection() OVERRIDE; virtual bool IsActive() OVERRIDE; virtual TextInputType GetTextInputType() const OVERRIDE; + virtual TextInputMode GetTextInputMode() const OVERRIDE; virtual bool CanComposeInline() const OVERRIDE; virtual bool IsCandidatePopupOpen() const OVERRIDE; virtual void AddObserver(InputMethodObserver* observer) OVERRIDE; @@ -67,6 +71,7 @@ class UI_EXPORT MockInputMethod : NON_EXPORTED_BASE(public InputMethod) { private: TextInputClient* text_input_client_; + bool is_sticky_text_input_client_; ObserverList<Observer> observer_list_; DISALLOW_COPY_AND_ASSIGN(MockInputMethod); diff --git a/chromium/ui/base/ime/text_input_client.h b/chromium/ui/base/ime/text_input_client.h index 2fd14a2cd4e..5eb4b5e7e44 100644 --- a/chromium/ui/base/ime/text_input_client.h +++ b/chromium/ui/base/ime/text_input_client.h @@ -11,9 +11,9 @@ #include "ui/base/ime/composition_text.h" #include "ui/base/ime/text_input_mode.h" #include "ui/base/ime/text_input_type.h" -#include "ui/base/range/range.h" #include "ui/base/ui_export.h" #include "ui/gfx/native_widget_types.h" +#include "ui/gfx/range/range.h" namespace gfx { class Rect; @@ -91,20 +91,20 @@ class UI_EXPORT TextInputClient { // Retrieves the UTF-16 based character range containing accessibled text in // the View. It must cover the composition and selection range. // Returns false if the information cannot be retrieved right now. - virtual bool GetTextRange(ui::Range* range) = 0; + virtual bool GetTextRange(gfx::Range* range) = 0; // Retrieves the UTF-16 based character range of current composition text. // Returns false if the information cannot be retrieved right now. - virtual bool GetCompositionTextRange(ui::Range* range) = 0; + virtual bool GetCompositionTextRange(gfx::Range* range) = 0; // Retrieves the UTF-16 based character range of current selection. // Returns false if the information cannot be retrieved right now. - virtual bool GetSelectionRange(ui::Range* range) = 0; + virtual bool GetSelectionRange(gfx::Range* range) = 0; // Selects the given UTF-16 based character range. Current composition text // will be confirmed before selecting the range. // Returns false if the operation is not supported. - virtual bool SetSelectionRange(const ui::Range& range) = 0; + virtual bool SetSelectionRange(const gfx::Range& range) = 0; // Deletes contents in the given UTF-16 based character range. Current // composition text will be confirmed before deleting the range. @@ -114,13 +114,13 @@ class UI_EXPORT TextInputClient { // GetSelectionRange has a race condition due to asynchronous IPCs between // browser and renderer. // Returns false if the operation is not supported. - virtual bool DeleteRange(const ui::Range& range) = 0; + virtual bool DeleteRange(const gfx::Range& range) = 0; // Retrieves the text content in a given UTF-16 based character range. // The result will be stored into |*text|. // Returns false if the operation is not supported or the specified range // is out of the text range returned by GetTextRange(). - virtual bool GetTextFromRange(const ui::Range& range, string16* text) = 0; + virtual bool GetTextFromRange(const gfx::Range& range, string16* text) = 0; // Miscellaneous ------------------------------------------------------------ diff --git a/chromium/ui/base/ime/win/imm32_manager.cc b/chromium/ui/base/ime/win/imm32_manager.cc index 7e595917a72..d418f6181b0 100644 --- a/chromium/ui/base/ime/win/imm32_manager.cc +++ b/chromium/ui/base/ime/win/imm32_manager.cc @@ -329,9 +329,9 @@ void IMM32Manager::GetCompositionInfo(HIMC imm_context, LPARAM lparam, // IMM32 does not support non-zero-width selection in a composition. So // always use the caret position as selection range. int cursor = ::ImmGetCompositionString(imm_context, GCS_CURSORPOS, NULL, 0); - composition->selection = ui::Range(cursor); + composition->selection = gfx::Range(cursor); } else { - composition->selection = ui::Range(0); + composition->selection = gfx::Range(0); } // Retrieve the clause segmentations and convert them to underlines. diff --git a/chromium/ui/base/ime/win/tsf_bridge.cc b/chromium/ui/base/ime/win/tsf_bridge.cc index 4186bc7883e..bf2820323ef 100644 --- a/chromium/ui/base/ime/win/tsf_bridge.cc +++ b/chromium/ui/base/ime/win/tsf_bridge.cc @@ -72,6 +72,24 @@ class TSFBridgeDelegate : public TSFBridge { // Returns true if already initialized. bool IsInitialized(); + // Updates or clears the association maintained in the TSF runtime between + // |attached_window_handle_| and the current document manager. Keeping this + // association updated solves some tricky event ordering issues between + // logical text input focus managed by Chrome and native text input focus + // managed by the OS. + // Background: + // TSF runtime monitors some Win32 messages such as WM_ACTIVATE to + // change the focused document manager. This is problematic when + // TSFBridge::SetFocusedClient is called first then the target window + // receives WM_ACTIVATE. This actually occurs in Aura environment where + // WM_NCACTIVATE is used as a trigger to restore text input focus. + // Caveats: + // TSF runtime does not increment the reference count of the attached + // document manager. See the comment inside the method body for + // details. + void UpdateAssociateFocus(); + void ClearAssociateFocus(); + // A triple of document manager, text store and binding cookie between // a context owned by the document manager and the text store. This is a // minimum working set of an editable document in TSF. @@ -110,12 +128,16 @@ class TSFBridgeDelegate : public TSFBridge { // Current focused text input client. Do not free |client_|. TextInputClient* client_; + // Represents the window that is currently owns text input focus. + HWND attached_window_handle_; + DISALLOW_COPY_AND_ASSIGN(TSFBridgeDelegate); }; TSFBridgeDelegate::TSFBridgeDelegate() : client_id_(TF_CLIENTID_NULL), - client_(NULL) { + client_(NULL), + attached_window_handle_(NULL) { } TSFBridgeDelegate::~TSFBridgeDelegate() { @@ -194,6 +216,8 @@ void TSFBridgeDelegate::OnTextInputTypeChanged(const TextInputClient* client) { return; } + UpdateAssociateFocus(); + TSFDocument* document = GetAssociatedDocument(); if (!document) return; @@ -241,7 +265,10 @@ void TSFBridgeDelegate::SetFocusedClient(HWND focused_window, DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type()); DCHECK(client); DCHECK(IsInitialized()); + if (attached_window_handle_ != focused_window) + ClearAssociateFocus(); client_ = client; + attached_window_handle_ = focused_window; for (TSFDocumentMap::iterator it = tsf_document_map_.begin(); it != tsf_document_map_.end(); ++it) { @@ -260,9 +287,11 @@ void TSFBridgeDelegate::RemoveFocusedClient(TextInputClient* client) { DCHECK(IsInitialized()); if (client_ != client) return; + ClearAssociateFocus(); client_ = NULL; + attached_window_handle_ = NULL; for (TSFDocumentMap::iterator it = tsf_document_map_.begin(); - it != tsf_document_map_.end(); ++it) { + it != tsf_document_map_.end(); ++it) { if (it->second.text_store.get() == NULL) continue; it->second.text_store->SetFocusedTextInputClient(NULL, NULL); @@ -413,13 +442,45 @@ bool TSFBridgeDelegate::IsInitialized() { return client_id_ != TF_CLIENTID_NULL; } +void TSFBridgeDelegate::UpdateAssociateFocus() { + if (attached_window_handle_ == NULL) + return; + TSFDocument* document = GetAssociatedDocument(); + if (document == NULL) { + ClearAssociateFocus(); + return; + } + // NOTE: ITfThreadMgr::AssociateFocus does not increment the ref count of + // the document manager to be attached. It is our responsibility to make sure + // the attached document manager will not be destroyed while it is attached. + // This should be true as long as TSFBridge::Shutdown() is called late phase + // of UI thread shutdown. + base::win::ScopedComPtr<ITfDocumentMgr> previous_focus; + thread_manager_->AssociateFocus( + attached_window_handle_, document->document_manager.get(), + previous_focus.Receive()); +} + +void TSFBridgeDelegate::ClearAssociateFocus() { + if (attached_window_handle_ == NULL) + return; + base::win::ScopedComPtr<ITfDocumentMgr> previous_focus; + thread_manager_->AssociateFocus( + attached_window_handle_, NULL, previous_focus.Receive()); +} + TSFBridgeDelegate::TSFDocument* TSFBridgeDelegate::GetAssociatedDocument() { if (!client_) return NULL; TSFDocumentMap::iterator it = tsf_document_map_.find(client_->GetTextInputType()); - if (it == tsf_document_map_.end()) - return &tsf_document_map_[TEXT_INPUT_TYPE_TEXT]; + if (it == tsf_document_map_.end()) { + it = tsf_document_map_.find(TEXT_INPUT_TYPE_TEXT); + // This check is necessary because it's possible that we failed to + // initialize |tsf_document_map_| and it has no TEXT_INPUT_TYPE_TEXT. + if (it == tsf_document_map_.end()) + return NULL; + } return &it->second; } diff --git a/chromium/ui/base/ime/win/tsf_event_router.cc b/chromium/ui/base/ime/win/tsf_event_router.cc index 51f66a267ac..4f34a048eec 100644 --- a/chromium/ui/base/ime/win/tsf_event_router.cc +++ b/chromium/ui/base/ime/win/tsf_event_router.cc @@ -11,8 +11,8 @@ #include "base/bind.h" #include "base/win/scoped_comptr.h" #include "base/win/metro.h" -#include "ui/base/range/range.h" #include "ui/base/win/atl_module.h" +#include "ui/gfx/range/range.h" namespace ui { @@ -56,9 +56,9 @@ class ATL_NO_VTABLE TSFEventRouter::Delegate void SetRouter(TSFEventRouter* router); private: - // Returns current composition range. Returns ui::Range::InvalidRange if there - // is no composition. - static ui::Range GetCompositionRange(ITfContext* context); + // Returns current composition range. Returns gfx::Range::InvalidRange if + // there is no composition. + static gfx::Range GetCompositionRange(ITfContext* context); // Returns true if the given |element_id| represents the candidate window. bool IsCandidateWindowInternal(DWORD element_id); @@ -85,7 +85,7 @@ class ATL_NO_VTABLE TSFEventRouter::Delegate DWORD ui_source_cookie_; TSFEventRouter* router_; - ui::Range previous_composition_range_; + gfx::Range previous_composition_range_; DISALLOW_COPY_AND_ASSIGN(Delegate); }; @@ -94,7 +94,7 @@ TSFEventRouter::Delegate::Delegate() : context_source_cookie_(TF_INVALID_COOKIE), ui_source_cookie_(TF_INVALID_COOKIE), router_(NULL), - previous_composition_range_(ui::Range::InvalidRange()) { + previous_composition_range_(gfx::Range::InvalidRange()) { } TSFEventRouter::Delegate::~Delegate() {} @@ -125,7 +125,7 @@ STDMETHODIMP TSFEventRouter::Delegate::OnEndEdit(ITfContext* context, if (FAILED(ranges->Next(1, range.Receive(), &fetched_count))) return S_OK; // Don't care about failures. - const ui::Range composition_range = GetCompositionRange(context); + const gfx::Range composition_range = GetCompositionRange(context); if (!previous_composition_range_.IsValid() && composition_range.IsValid()) router_->OnTSFStartComposition(); @@ -214,35 +214,35 @@ bool TSFEventRouter::Delegate::IsImeComposing() { } // static -ui::Range TSFEventRouter::Delegate::GetCompositionRange( +gfx::Range TSFEventRouter::Delegate::GetCompositionRange( ITfContext* context) { DCHECK(context); base::win::ScopedComPtr<ITfContextComposition> context_composition; if (FAILED(context_composition.QueryFrom(context))) - return ui::Range::InvalidRange(); + return gfx::Range::InvalidRange(); base::win::ScopedComPtr<IEnumITfCompositionView> enum_composition_view; if (FAILED(context_composition->EnumCompositions( enum_composition_view.Receive()))) - return ui::Range::InvalidRange(); + return gfx::Range::InvalidRange(); base::win::ScopedComPtr<ITfCompositionView> composition_view; if (enum_composition_view->Next(1, composition_view.Receive(), NULL) != S_OK) - return ui::Range::InvalidRange(); + return gfx::Range::InvalidRange(); base::win::ScopedComPtr<ITfRange> range; if (FAILED(composition_view->GetRange(range.Receive()))) - return ui::Range::InvalidRange(); + return gfx::Range::InvalidRange(); base::win::ScopedComPtr<ITfRangeACP> range_acp; if (FAILED(range_acp.QueryFrom(range))) - return ui::Range::InvalidRange(); + return gfx::Range::InvalidRange(); LONG start = 0; LONG length = 0; if (FAILED(range_acp->GetExtent(&start, &length))) - return ui::Range::InvalidRange(); + return gfx::Range::InvalidRange(); - return ui::Range(start, start + length); + return gfx::Range(start, start + length); } bool TSFEventRouter::Delegate::IsCandidateWindowInternal(DWORD element_id) { @@ -292,7 +292,7 @@ void TSFEventRouter::OnTSFStartComposition() { observer_->OnTSFStartComposition(); } -void TSFEventRouter::OnTextUpdated(const ui::Range& composition_range) { +void TSFEventRouter::OnTextUpdated(const gfx::Range& composition_range) { observer_->OnTextUpdated(composition_range); } diff --git a/chromium/ui/base/ime/win/tsf_event_router.h b/chromium/ui/base/ime/win/tsf_event_router.h index be2311c9fce..04a2a1e9eb0 100644 --- a/chromium/ui/base/ime/win/tsf_event_router.h +++ b/chromium/ui/base/ime/win/tsf_event_router.h @@ -15,8 +15,8 @@ #include "base/callback.h" #include "base/compiler_specific.h" #include "ui/base/ime/text_input_type.h" -#include "ui/base/range/range.h" #include "ui/base/ui_export.h" +#include "ui/gfx/range/range.h" struct ITfDocumentMgr; @@ -33,8 +33,8 @@ class TSFEventRouterObserver { virtual void OnTSFStartComposition() {} // Called when the text contents are updated. If there is no composition, - // ui::Range::InvalidRange is passed to |composition_range|. - virtual void OnTextUpdated(const ui::Range& composition_range) {} + // gfx::Range::InvalidRange is passed to |composition_range|. + virtual void OnTextUpdated(const gfx::Range& composition_range) {} // Called when a composition is terminated. virtual void OnTSFEndComposition() {} @@ -60,7 +60,7 @@ class UI_EXPORT TSFEventRouter { // Callbacks from the TSFEventRouterDelegate: void OnCandidateWindowCountChanged(size_t window_count); void OnTSFStartComposition(); - void OnTextUpdated(const ui::Range& composition_range); + void OnTextUpdated(const gfx::Range& composition_range); void OnTSFEndComposition(); // Sets |thread_manager| to be monitored. |thread_manager| can be NULL. diff --git a/chromium/ui/base/ime/win/tsf_input_scope.cc b/chromium/ui/base/ime/win/tsf_input_scope.cc index cb6792e9bd2..06481e9d8f0 100644 --- a/chromium/ui/base/ime/win/tsf_input_scope.cc +++ b/chromium/ui/base/ime/win/tsf_input_scope.cc @@ -4,8 +4,7 @@ #include "ui/base/ime/win/tsf_input_scope.h" -#include <InputScope.h> -#include <vector> +#include <algorithm> #include "base/compiler_specific.h" #include "base/logging.h" @@ -16,6 +15,20 @@ namespace ui { namespace tsf_inputscope { namespace { +void AppendNonTrivialInputScope(std::vector<InputScope>* input_scopes, + InputScope input_scope) { + DCHECK(input_scopes); + + if (input_scope == IS_DEFAULT) + return; + + if (std::find(input_scopes->begin(), input_scopes->end(), input_scope) != + input_scopes->end()) + return; + + input_scopes->push_back(input_scope); +} + class TSFInputScope : public ITfInputScope { public: explicit TSFInputScope(const std::vector<InputScope>& input_scopes) @@ -145,11 +158,6 @@ InputScope ConvertTextInputTypeToInputScope(TextInputType text_input_type) { InputScope ConvertTextInputModeToInputScope(TextInputMode text_input_mode) { switch (text_input_mode) { - case TEXT_INPUT_MODE_VERBATIM: - case TEXT_INPUT_MODE_LATIN: - case TEXT_INPUT_MODE_LATIN_NAME: - case TEXT_INPUT_MODE_LATIN_PROSE: - return IS_ALPHANUMERIC_HALFWIDTH; case TEXT_INPUT_MODE_FULL_WIDTH_LATIN: return IS_ALPHANUMERIC_FULLWIDTH; case TEXT_INPUT_MODE_KANA: @@ -171,10 +179,24 @@ InputScope ConvertTextInputModeToInputScope(TextInputMode text_input_mode) { } // namespace -ITfInputScope* CreateInputScope(TextInputType text_input_type) { - std::vector<InputScope> input_scopes(1); - input_scopes.push_back(ConvertTextInputTypeToInputScope(text_input_type)); - return new TSFInputScope(input_scopes); +std::vector<InputScope> GetInputScopes(TextInputType text_input_type, + TextInputMode text_input_mode) { + std::vector<InputScope> input_scopes; + + AppendNonTrivialInputScope(&input_scopes, + ConvertTextInputTypeToInputScope(text_input_type)); + AppendNonTrivialInputScope(&input_scopes, + ConvertTextInputModeToInputScope(text_input_mode)); + + if (input_scopes.empty()) + input_scopes.push_back(IS_DEFAULT); + + return input_scopes; +} + +ITfInputScope* CreateInputScope(TextInputType text_input_type, + TextInputMode text_input_mode) { + return new TSFInputScope(GetInputScopes(text_input_type, text_input_mode)); } void SetInputScopeForTsfUnawareWindow( @@ -185,14 +207,10 @@ void SetInputScopeForTsfUnawareWindow( if (!set_input_scopes) return; - InputScope input_scopes[] = { - ConvertTextInputTypeToInputScope(text_input_type), - ConvertTextInputModeToInputScope(text_input_mode), - }; - - set_input_scopes(window_handle, input_scopes, - (input_scopes[0] == input_scopes[1] ? 1 : 2), NULL, 0, NULL, - NULL); + std::vector<InputScope> input_scopes = GetInputScopes(text_input_type, + text_input_mode); + set_input_scopes(window_handle, &input_scopes[0], input_scopes.size(), NULL, + 0, NULL, NULL); } } // namespace tsf_inputscope diff --git a/chromium/ui/base/ime/win/tsf_input_scope.h b/chromium/ui/base/ime/win/tsf_input_scope.h index 24ac94ce2fe..2e5856c60d8 100644 --- a/chromium/ui/base/ime/win/tsf_input_scope.h +++ b/chromium/ui/base/ime/win/tsf_input_scope.h @@ -5,24 +5,32 @@ #ifndef UI_BASE_IME_WIN_TSF_INPUT_SCOPE_H_ #define UI_BASE_IME_WIN_TSF_INPUT_SCOPE_H_ +#include <InputScope.h> #include <Windows.h> +#include <vector> #include "base/basictypes.h" #include "ui/base/ime/text_input_mode.h" #include "ui/base/ime/text_input_type.h" #include "ui/base/ui_export.h" -struct ITfInputScope; - namespace ui { namespace tsf_inputscope { +// Returns InputScope list corresoponding to ui::TextInputType and +// ui::TextInputMode. +// This function is only used from following functions but declared for test. +UI_EXPORT std::vector<InputScope> GetInputScopes(TextInputType text_input_type, + TextInputMode text_input_mode); + // Returns an instance of ITfInputScope, which is the Windows-specific -// category representation corresponding to ui::TextInputType that we are -// using to specify the expected text type in the target field. +// category representation corresponding to ui::TextInputType and +// ui::TextInputMode that we are using to specify the expected text type +// in the target field. // The returned instance has 0 reference count. The caller must maintain its // reference count. -UI_EXPORT ITfInputScope* CreateInputScope(TextInputType text_input_type); +UI_EXPORT ITfInputScope* CreateInputScope(TextInputType text_input_type, + TextInputMode text_input_mode); // A wrapper of the SetInputScopes API exported by msctf.dll. // http://msdn.microsoft.com/en-us/library/windows/desktop/ms629026.aspx diff --git a/chromium/ui/base/ime/win/tsf_input_scope_unittest.cc b/chromium/ui/base/ime/win/tsf_input_scope_unittest.cc new file mode 100644 index 00000000000..de6ede17ffd --- /dev/null +++ b/chromium/ui/base/ime/win/tsf_input_scope_unittest.cc @@ -0,0 +1,121 @@ +// 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 "ui/base/ime/win/tsf_input_scope.h" + +#include <InputScope.h> + +#include "testing/gtest/include/gtest/gtest.h" + +namespace ui { +namespace { + +struct GetInputScopesTestCase { + TextInputType input_type; + TextInputMode input_mode; + size_t expected_size; + InputScope expected_input_scopes[2]; +}; + +// Google Test pretty-printer. +void PrintTo(const GetInputScopesTestCase& data, std::ostream* os) { + *os << " input_type: " << testing::PrintToString(data.input_type) + << "; input_mode: " << testing::PrintToString(data.input_mode); +} + +class TSFInputScopeTest + : public testing::TestWithParam<GetInputScopesTestCase> { +}; + +const GetInputScopesTestCase kGetInputScopesTestCases[] = { + // Test cases of TextInputType. + {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_DEFAULT, + 1, {IS_DEFAULT}}, + {TEXT_INPUT_TYPE_TEXT, TEXT_INPUT_MODE_DEFAULT, + 1, {IS_DEFAULT}}, + {TEXT_INPUT_TYPE_PASSWORD, TEXT_INPUT_MODE_DEFAULT, + 1, {IS_PASSWORD}}, + {TEXT_INPUT_TYPE_SEARCH, TEXT_INPUT_MODE_DEFAULT, + 1, {IS_SEARCH}}, + {TEXT_INPUT_TYPE_EMAIL, TEXT_INPUT_MODE_DEFAULT, + 1, {IS_EMAIL_SMTPEMAILADDRESS}}, + {TEXT_INPUT_TYPE_NUMBER, TEXT_INPUT_MODE_DEFAULT, + 1, {IS_NUMBER}}, + {TEXT_INPUT_TYPE_TELEPHONE, TEXT_INPUT_MODE_DEFAULT, + 1, {IS_TELEPHONE_FULLTELEPHONENUMBER}}, + {TEXT_INPUT_TYPE_URL, TEXT_INPUT_MODE_DEFAULT, + 1, {IS_URL}}, + {TEXT_INPUT_TYPE_DATE, TEXT_INPUT_MODE_DEFAULT, + 1, {IS_DEFAULT}}, + {TEXT_INPUT_TYPE_DATE_TIME, TEXT_INPUT_MODE_DEFAULT, + 1, {IS_DEFAULT}}, + {TEXT_INPUT_TYPE_DATE_TIME_LOCAL, TEXT_INPUT_MODE_DEFAULT, + 1, {IS_DEFAULT}}, + {TEXT_INPUT_TYPE_MONTH, TEXT_INPUT_MODE_DEFAULT, + 1, {IS_DEFAULT}}, + {TEXT_INPUT_TYPE_TIME, TEXT_INPUT_MODE_DEFAULT, + 1, {IS_DEFAULT}}, + {TEXT_INPUT_TYPE_WEEK, TEXT_INPUT_MODE_DEFAULT, + 1, {IS_DEFAULT}}, + {TEXT_INPUT_TYPE_TEXT_AREA, TEXT_INPUT_MODE_DEFAULT, + 1, {IS_DEFAULT}}, + {TEXT_INPUT_TYPE_CONTENT_EDITABLE, TEXT_INPUT_MODE_DEFAULT, + 1, {IS_DEFAULT}}, + {TEXT_INPUT_TYPE_DATE_TIME_FIELD, TEXT_INPUT_MODE_DEFAULT, + 1, {IS_DEFAULT}}, + // Test cases of TextInputMode. + {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_DEFAULT, + 1, {IS_DEFAULT}}, + {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_VERBATIM, + 1, {IS_DEFAULT}}, + {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_LATIN, + 1, {IS_DEFAULT}}, + {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_LATIN_NAME, + 1, {IS_DEFAULT}}, + {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_LATIN_PROSE, + 1, {IS_DEFAULT}}, + {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_FULL_WIDTH_LATIN, + 1, {IS_ALPHANUMERIC_FULLWIDTH}}, + {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_KANA, + 1, {IS_HIRAGANA}}, + {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_KATAKANA, + 1, {IS_KATAKANA_FULLWIDTH}}, + {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_NUMERIC, + 1, {IS_NUMBER}}, + {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_TEL, + 1, {IS_TELEPHONE_FULLTELEPHONENUMBER}}, + {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_EMAIL, + 1, {IS_EMAIL_SMTPEMAILADDRESS}}, + {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_URL, + 1, {IS_URL}}, + // Mixed test cases. + {TEXT_INPUT_TYPE_SEARCH, TEXT_INPUT_MODE_KANA, + 2, {IS_SEARCH, IS_HIRAGANA}}, + {TEXT_INPUT_TYPE_EMAIL, TEXT_INPUT_MODE_EMAIL, + 1, {IS_EMAIL_SMTPEMAILADDRESS}}, + {TEXT_INPUT_TYPE_NUMBER, TEXT_INPUT_MODE_NUMERIC, + 1, {IS_NUMBER}}, + {TEXT_INPUT_TYPE_TELEPHONE, TEXT_INPUT_MODE_TEL, + 1, {IS_TELEPHONE_FULLTELEPHONENUMBER}}, + {TEXT_INPUT_TYPE_URL, TEXT_INPUT_MODE_URL, + 1, {IS_URL}}, +}; + +TEST_P(TSFInputScopeTest, GetInputScopes) { + const GetInputScopesTestCase& test_case = GetParam(); + + std::vector<InputScope> input_scopes = tsf_inputscope::GetInputScopes( + test_case.input_type, test_case.input_mode); + + EXPECT_EQ(test_case.expected_size, input_scopes.size()); + for (size_t i = 0; i < test_case.expected_size; ++i) + EXPECT_EQ(test_case.expected_input_scopes[i], input_scopes[i]); +} + +INSTANTIATE_TEST_CASE_P(, + TSFInputScopeTest, + ::testing::ValuesIn(kGetInputScopesTestCases)); + +} // namespace +} // namespace ui diff --git a/chromium/ui/base/ime/win/tsf_text_store.cc b/chromium/ui/base/ime/win/tsf_text_store.cc index 40f02bf4ea1..abd19ae8a90 100644 --- a/chromium/ui/base/ime/win/tsf_text_store.cc +++ b/chromium/ui/base/ime/win/tsf_text_store.cc @@ -8,6 +8,10 @@ #include <InputScope.h> #include <OleCtl.h> +#include <algorithm> + +#include <algorithm> + #include "base/win/scoped_variant.h" #include "ui/base/ime/text_input_client.h" #include "ui/base/ime/win/tsf_input_scope.h" @@ -585,6 +589,8 @@ STDMETHODIMP TSFTextStore::RequestSupportedAttrs( const TS_ATTRID* attribute_buffer) { if (!attribute_buffer) return E_INVALIDARG; + if (!text_input_client_) + return E_FAIL; // We support only input scope attribute. for (size_t i = 0; i < attribute_buffer_size; ++i) { if (IsEqualGUID(GUID_PROP_INPUTSCOPE, attribute_buffer[i])) @@ -601,6 +607,8 @@ STDMETHODIMP TSFTextStore::RetrieveRequestedAttrs( return E_INVALIDARG; if (!attribute_buffer) return E_INVALIDARG; + if (!text_input_client_) + return E_UNEXPECTED; // We support only input scope attribute. *attribute_buffer_copied = 0; if (attribute_buffer_size == 0) @@ -610,7 +618,8 @@ STDMETHODIMP TSFTextStore::RetrieveRequestedAttrs( attribute_buffer[0].idAttr = GUID_PROP_INPUTSCOPE; attribute_buffer[0].varValue.vt = VT_UNKNOWN; attribute_buffer[0].varValue.punkVal = tsf_inputscope::CreateInputScope( - text_input_client_->GetTextInputType()); + text_input_client_->GetTextInputType(), + text_input_client_->GetTextInputMode()); attribute_buffer[0].varValue.punkVal->AddRef(); *attribute_buffer_copied = 1; return S_OK; diff --git a/chromium/ui/base/ime/win/tsf_text_store.h b/chromium/ui/base/ime/win/tsf_text_store.h index 86ceeba4804..87cd6b42991 100644 --- a/chromium/ui/base/ime/win/tsf_text_store.h +++ b/chromium/ui/base/ime/win/tsf_text_store.h @@ -13,8 +13,8 @@ #include "base/strings/string16.h" #include "base/win/scoped_comptr.h" #include "ui/base/ime/composition_underline.h" -#include "ui/base/range/range.h" #include "ui/base/ui_export.h" +#include "ui/gfx/range/range.h" namespace ui { class TextInputClient; @@ -258,7 +258,7 @@ class UI_EXPORT TSFTextStore : public ITextStoreACP, // |string_buffer_|: "aiueo" // |selection_.start()|: 1 // |selection_.end()|: 4 - Range selection_; + gfx::Range selection_; // |start_offset| and |end_offset| of |composition_undelines_| indicates // the offsets in |string_buffer_|. diff --git a/chromium/ui/base/ime/win/tsf_text_store_unittest.cc b/chromium/ui/base/ime/win/tsf_text_store_unittest.cc index 62772f246c7..82268c9e584 100644 --- a/chromium/ui/base/ime/win/tsf_text_store_unittest.cc +++ b/chromium/ui/base/ime/win/tsf_text_store_unittest.cc @@ -4,7 +4,13 @@ #include "ui/base/ime/win/tsf_text_store.h" +#include <initguid.h> // for GUID_NULL and GUID_PROP_INPUTSCOPE +#include <InputScope.h> +#include <OleCtl.h> + +#include "base/memory/ref_counted.h" #include "base/win/scoped_com_initializer.h" +#include "base/win/scoped_variant.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/gmock/include/gmock/gmock.h" #include "ui/base/ime/text_input_client.h" @@ -15,7 +21,6 @@ using testing::Invoke; using testing::Return; namespace ui { - namespace { class MockTextInputClient : public TextInputClient { @@ -33,12 +38,12 @@ class MockTextInputClient : public TextInputClient { MOCK_METHOD0(GetCaretBounds, gfx::Rect()); MOCK_METHOD2(GetCompositionCharacterBounds, bool(uint32, gfx::Rect*)); MOCK_METHOD0(HasCompositionText, bool()); - MOCK_METHOD1(GetTextRange, bool(ui::Range*)); - MOCK_METHOD1(GetCompositionTextRange, bool(ui::Range*)); - MOCK_METHOD1(GetSelectionRange, bool(ui::Range*)); - MOCK_METHOD1(SetSelectionRange, bool(const ui::Range&)); - MOCK_METHOD1(DeleteRange, bool(const ui::Range&)); - MOCK_METHOD2(GetTextFromRange, bool(const ui::Range&, string16*)); + MOCK_METHOD1(GetTextRange, bool(gfx::Range*)); + MOCK_METHOD1(GetCompositionTextRange, bool(gfx::Range*)); + MOCK_METHOD1(GetSelectionRange, bool(gfx::Range*)); + MOCK_METHOD1(SetSelectionRange, bool(const gfx::Range&)); + MOCK_METHOD1(DeleteRange, bool(const gfx::Range&)); + MOCK_METHOD2(GetTextFromRange, bool(const gfx::Range&, string16*)); MOCK_METHOD0(OnInputMethodChanged, void()); MOCK_METHOD1(ChangeTextDirectionAndLayoutAlignment, bool(base::i18n::TextDirection)); @@ -48,8 +53,7 @@ class MockTextInputClient : public TextInputClient { class MockStoreACPSink : public ITextStoreACPSink { public: - MockStoreACPSink() : ref_count_(0) { - } + MockStoreACPSink() : ref_count_(0) {} // IUnknown virtual ULONG STDMETHODCALLTYPE AddRef() OVERRIDE { @@ -94,36 +98,36 @@ class MockStoreACPSink : public ITextStoreACPSink { HRESULT()); private: - ~MockStoreACPSink() { - } + virtual ~MockStoreACPSink() {} volatile LONG ref_count_; }; +const HWND kWindowHandle = reinterpret_cast<HWND>(1); + } // namespace class TSFTextStoreTest : public testing::Test { protected: virtual void SetUp() OVERRIDE { text_store_ = new TSFTextStore(); - text_store_->AddRef(); sink_ = new MockStoreACPSink(); - sink_->AddRef(); EXPECT_EQ(S_OK, text_store_->AdviseSink(IID_ITextStoreACPSink, sink_, TS_AS_ALL_SINKS)); - text_store_->SetFocusedTextInputClient(0, &text_input_client_); + text_store_->SetFocusedTextInputClient(kWindowHandle, + &text_input_client_); } virtual void TearDown() OVERRIDE { EXPECT_EQ(S_OK, text_store_->UnadviseSink(sink_)); - sink_->Release(); - text_store_->Release(); + sink_ = NULL; + text_store_ = NULL; } base::win::ScopedCOMInitializer com_initializer_; MockTextInputClient text_input_client_; - TSFTextStore* text_store_; - MockStoreACPSink* sink_; + scoped_refptr<TSFTextStore> text_store_; + scoped_refptr<MockStoreACPSink> sink_; }; class TSFTextStoreTestCallback { @@ -139,7 +143,7 @@ class TSFTextStoreTestCallback { bool* edit_flag() { return &text_store_->edit_flag_; } string16* string_buffer() { return &text_store_->string_buffer_; } size_t* committed_size() { return &text_store_->committed_size_; } - Range* selection() { return &text_store_->selection_; } + gfx::Range* selection() { return &text_store_->selection_; } CompositionUnderlines* composition_undelines() { return &text_store_->composition_undelines_; } @@ -161,8 +165,8 @@ class TSFTextStoreTestCallback { bool HasReadWriteLock() const { return text_store_->HasReadWriteLock(); } void GetSelectionTest(LONG expected_acp_start, LONG expected_acp_end) { - TS_SELECTION_ACP selection; - ULONG fetched; + TS_SELECTION_ACP selection = {}; + ULONG fetched = 0; EXPECT_EQ(S_OK, text_store_->GetSelection(0, 1, &selection, &fetched)); EXPECT_EQ(1, fetched); EXPECT_EQ(expected_acp_start, selection.acpStart); @@ -170,7 +174,7 @@ class TSFTextStoreTestCallback { } void SetSelectionTest(LONG acp_start, LONG acp_end, HRESULT expected_result) { - TS_SELECTION_ACP selection; + TS_SELECTION_ACP selection = {}; selection.acpStart = acp_start; selection.acpEnd = acp_end; selection.style.ase = TS_AE_NONE; @@ -183,7 +187,7 @@ class TSFTextStoreTestCallback { void SetTextTest(LONG acp_start, LONG acp_end, const string16& text, HRESULT error_code) { - TS_TEXTCHANGE change; + TS_TEXTCHANGE change = {}; ASSERT_EQ(error_code, text_store_->SetText(0, acp_start, acp_end, text.c_str(), text.size(), &change)); @@ -197,11 +201,11 @@ class TSFTextStoreTestCallback { void GetTextTest(LONG acp_start, LONG acp_end, const string16& expected_string, LONG expected_next_acp) { - wchar_t buffer[1024]; - ULONG text_buffer_copied; - TS_RUNINFO run_info; - ULONG run_info_buffer_copied; - LONG next_acp; + wchar_t buffer[1024] = {}; + ULONG text_buffer_copied = 0; + TS_RUNINFO run_info = {}; + ULONG run_info_buffer_copied = 0; + LONG next_acp = 0; ASSERT_EQ(S_OK, text_store_->GetText(acp_start, acp_end, buffer, 1024, &text_buffer_copied, @@ -216,11 +220,11 @@ class TSFTextStoreTestCallback { } void GetTextErrorTest(LONG acp_start, LONG acp_end, HRESULT error_code) { - wchar_t buffer[1024]; - ULONG text_buffer_copied; - TS_RUNINFO run_info; - ULONG run_info_buffer_copied; - LONG next_acp; + wchar_t buffer[1024] = {}; + ULONG text_buffer_copied = 0; + TS_RUNINFO run_info = {}; + ULONG run_info_buffer_copied = 0; + LONG next_acp = 0; EXPECT_EQ(error_code, text_store_->GetText(acp_start, acp_end, buffer, 1024, &text_buffer_copied, @@ -233,8 +237,9 @@ class TSFTextStoreTestCallback { LONG expected_change_start, LONG expected_change_old_end, LONG expected_change_new_end) { - LONG start, end; - TS_TEXTCHANGE change; + LONG start = 0; + LONG end = 0; + TS_TEXTCHANGE change = {}; EXPECT_EQ(S_OK, text_store_->InsertTextAtSelection(0, buffer, buffer_size, &start, &end, &change)); @@ -249,7 +254,8 @@ class TSFTextStoreTestCallback { ULONG buffer_size, LONG expected_start, LONG expected_end) { - LONG start, end; + LONG start = 0; + LONG end = 0; EXPECT_EQ(S_OK, text_store_->InsertTextAtSelection(TS_IAS_QUERYONLY, buffer, buffer_size, &start, &end, @@ -261,8 +267,8 @@ class TSFTextStoreTestCallback { void GetTextExtTest(TsViewCookie view_cookie, LONG acp_start, LONG acp_end, LONG expected_left, LONG expected_top, LONG expected_right, LONG expected_bottom) { - RECT rect; - BOOL clipped; + RECT rect = {}; + BOOL clipped = FALSE; EXPECT_EQ(S_OK, text_store_->GetTextExt(view_cookie, acp_start, acp_end, &rect, &clipped)); EXPECT_EQ(expected_left, rect.left); @@ -274,29 +280,34 @@ class TSFTextStoreTestCallback { void GetTextExtNoLayoutTest(TsViewCookie view_cookie, LONG acp_start, LONG acp_end) { - RECT rect; - BOOL clipped; + RECT rect = {}; + BOOL clipped = FALSE; EXPECT_EQ(TS_E_NOLAYOUT, text_store_->GetTextExt(view_cookie, acp_start, acp_end, &rect, &clipped)); } - TSFTextStore* text_store_; + scoped_refptr<TSFTextStore> text_store_; + + private: + DISALLOW_COPY_AND_ASSIGN(TSFTextStoreTestCallback); }; +namespace { + +const HRESULT kInvalidResult = 0x12345678; + TEST_F(TSFTextStoreTest, GetStatusTest) { - TS_STATUS status; + TS_STATUS status = {}; EXPECT_EQ(S_OK, text_store_->GetStatus(&status)); EXPECT_EQ(0, status.dwDynamicFlags); EXPECT_EQ(TS_SS_TRANSITORY | TS_SS_NOHIDDENTEXT, status.dwStaticFlags); } - class SyncRequestLockTestCallback : public TSFTextStoreTestCallback { public: explicit SyncRequestLockTestCallback(TSFTextStore* text_store) - : TSFTextStoreTestCallback(text_store) { - } + : TSFTextStoreTestCallback(text_store) {} HRESULT LockGranted1(DWORD flags) { EXPECT_TRUE(HasReadLock()); @@ -313,7 +324,7 @@ class SyncRequestLockTestCallback : public TSFTextStoreTestCallback { HRESULT LockGranted3(DWORD flags) { EXPECT_TRUE(HasReadLock()); EXPECT_FALSE(HasReadWriteLock()); - HRESULT result; + HRESULT result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result)); EXPECT_EQ(TS_E_SYNCHRONOUS, result); return S_OK; @@ -322,7 +333,7 @@ class SyncRequestLockTestCallback : public TSFTextStoreTestCallback { HRESULT LockGranted4(DWORD flags) { EXPECT_TRUE(HasReadLock()); EXPECT_FALSE(HasReadWriteLock()); - HRESULT result; + HRESULT result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result)); EXPECT_EQ(TS_E_SYNCHRONOUS, result); @@ -332,7 +343,7 @@ class SyncRequestLockTestCallback : public TSFTextStoreTestCallback { HRESULT LockGranted5(DWORD flags) { EXPECT_TRUE(HasReadLock()); EXPECT_TRUE(HasReadWriteLock()); - HRESULT result; + HRESULT result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result)); EXPECT_EQ(TS_E_SYNCHRONOUS, result); return S_OK; @@ -341,12 +352,15 @@ class SyncRequestLockTestCallback : public TSFTextStoreTestCallback { HRESULT LockGranted6(DWORD flags) { EXPECT_TRUE(HasReadLock()); EXPECT_TRUE(HasReadWriteLock()); - HRESULT result; + HRESULT result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result)); EXPECT_EQ(TS_E_SYNCHRONOUS, result); return S_OK; } + + private: + DISALLOW_COPY_AND_ASSIGN(SyncRequestLockTestCallback); }; TEST_F(TSFTextStoreTest, SynchronousRequestLockTest) { @@ -359,21 +373,25 @@ TEST_F(TSFTextStoreTest, SynchronousRequestLockTest) { .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted5)) .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted6)); - HRESULT result; + HRESULT result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result)); EXPECT_EQ(S_OK, result); + result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result)); EXPECT_EQ(S_OK, result); EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result)); EXPECT_EQ(S_OK, result); + result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result)); EXPECT_EQ(S_OK, result); + result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result)); EXPECT_EQ(S_OK, result); + result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result)); EXPECT_EQ(S_OK, result); @@ -383,15 +401,14 @@ class AsyncRequestLockTestCallback : public TSFTextStoreTestCallback { public: explicit AsyncRequestLockTestCallback(TSFTextStore* text_store) : TSFTextStoreTestCallback(text_store), - state_(0) { - } + state_(0) {} HRESULT LockGranted1(DWORD flags) { EXPECT_EQ(0, state_); state_ = 1; EXPECT_TRUE(HasReadLock()); EXPECT_FALSE(HasReadWriteLock()); - HRESULT result; + HRESULT result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result)); EXPECT_EQ(TS_S_ASYNC, result); EXPECT_EQ(1, state_); @@ -403,7 +420,7 @@ class AsyncRequestLockTestCallback : public TSFTextStoreTestCallback { EXPECT_EQ(2, state_); EXPECT_TRUE(HasReadLock()); EXPECT_FALSE(HasReadWriteLock()); - HRESULT result; + HRESULT result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); EXPECT_EQ(TS_S_ASYNC, result); EXPECT_EQ(2, state_); @@ -415,7 +432,7 @@ class AsyncRequestLockTestCallback : public TSFTextStoreTestCallback { EXPECT_EQ(3, state_); EXPECT_TRUE(HasReadLock()); EXPECT_TRUE(HasReadWriteLock()); - HRESULT result; + HRESULT result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); EXPECT_EQ(TS_S_ASYNC, result); EXPECT_EQ(3, state_); @@ -427,7 +444,7 @@ class AsyncRequestLockTestCallback : public TSFTextStoreTestCallback { EXPECT_EQ(4, state_); EXPECT_TRUE(HasReadLock()); EXPECT_TRUE(HasReadWriteLock()); - HRESULT result; + HRESULT result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result)); EXPECT_EQ(TS_S_ASYNC, result); EXPECT_EQ(4, state_); @@ -445,6 +462,8 @@ class AsyncRequestLockTestCallback : public TSFTextStoreTestCallback { private: int state_; + + DISALLOW_COPY_AND_ASSIGN(AsyncRequestLockTestCallback); }; TEST_F(TSFTextStoreTest, AsynchronousRequestLockTest) { @@ -456,7 +475,7 @@ TEST_F(TSFTextStoreTest, AsynchronousRequestLockTest) { .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted4)) .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted5)); - HRESULT result; + HRESULT result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result)); EXPECT_EQ(S_OK, result); } @@ -465,8 +484,7 @@ class RequestLockTextChangeTestCallback : public TSFTextStoreTestCallback { public: explicit RequestLockTextChangeTestCallback(TSFTextStore* text_store) : TSFTextStoreTestCallback(text_store), - state_(0) { - } + state_(0) {} HRESULT LockGranted1(DWORD flags) { EXPECT_EQ(0, state_); @@ -499,7 +517,7 @@ class RequestLockTextChangeTestCallback : public TSFTextStoreTestCallback { HRESULT OnTextChange(DWORD flags, const TS_TEXTCHANGE* change) { EXPECT_EQ(4, state_); - HRESULT result; + HRESULT result = kInvalidResult; state_ = 5; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); EXPECT_EQ(S_OK, result); @@ -518,6 +536,8 @@ class RequestLockTextChangeTestCallback : public TSFTextStoreTestCallback { private: int state_; + + DISALLOW_COPY_AND_ASSIGN(RequestLockTextChangeTestCallback); }; TEST_F(TSFTextStoreTest, RequestLockOnTextChangeTest) { @@ -542,7 +562,7 @@ TEST_F(TSFTextStoreTest, RequestLockOnTextChangeTest) { .WillOnce(Invoke(&callback, &RequestLockTextChangeTestCallback::SetCompositionText)); - HRESULT result; + HRESULT result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); EXPECT_EQ(S_OK, result); } @@ -550,8 +570,7 @@ TEST_F(TSFTextStoreTest, RequestLockOnTextChangeTest) { class SelectionTestCallback : public TSFTextStoreTestCallback { public: explicit SelectionTestCallback(TSFTextStore* text_store) - : TSFTextStoreTestCallback(text_store) { - } + : TSFTextStoreTestCallback(text_store) {} HRESULT ReadLockGranted(DWORD flags) { SetInternalState(L"", 0, 0, 0); @@ -631,23 +650,21 @@ TEST_F(TSFTextStoreTest, SetGetSelectionTest) { .WillOnce(Invoke(&callback, &SelectionTestCallback::ReadWriteLockGranted)); - TS_SELECTION_ACP selection_buffer; - ULONG fetched_count; + TS_SELECTION_ACP selection_buffer = {}; + ULONG fetched_count = 0; EXPECT_EQ(TS_E_NOLOCK, text_store_->GetSelection(0, 1, &selection_buffer, &fetched_count)); - HRESULT result; + HRESULT result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result)); EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); } - class SetGetTextTestCallback : public TSFTextStoreTestCallback { public: explicit SetGetTextTestCallback(TSFTextStore* text_store) - : TSFTextStoreTestCallback(text_store) { - } + : TSFTextStoreTestCallback(text_store) {} HRESULT ReadLockGranted(DWORD flags) { SetTextTest(0, 0, L"", TF_E_NOLOCK); @@ -820,6 +837,9 @@ class SetGetTextTestCallback : public TSFTextStoreTestCallback { return S_OK; } + + private: + DISALLOW_COPY_AND_ASSIGN(SetGetTextTestCallback); }; TEST_F(TSFTextStoreTest, SetGetTextTest) { @@ -829,19 +849,19 @@ TEST_F(TSFTextStoreTest, SetGetTextTest) { .WillOnce(Invoke(&callback, &SetGetTextTestCallback::ReadWriteLockGranted)); - wchar_t buffer[1024]; - ULONG text_buffer_copied; - TS_RUNINFO run_info; - ULONG run_info_buffer_copied; - LONG next_acp; + wchar_t buffer[1024] = {}; + ULONG text_buffer_copied = 0; + TS_RUNINFO run_info = {}; + ULONG run_info_buffer_copied = 0; + LONG next_acp = 0; EXPECT_EQ(TF_E_NOLOCK, text_store_->GetText(0, -1, buffer, 1024, &text_buffer_copied, &run_info, 1, &run_info_buffer_copied, &next_acp)); - TS_TEXTCHANGE change; + TS_TEXTCHANGE change = {}; EXPECT_EQ(TF_E_NOLOCK, text_store_->SetText(0, 0, 0, L"abc", 3, &change)); - HRESULT result; + HRESULT result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result)); EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); } @@ -849,8 +869,7 @@ TEST_F(TSFTextStoreTest, SetGetTextTest) { class InsertTextAtSelectionTestCallback : public TSFTextStoreTestCallback { public: explicit InsertTextAtSelectionTestCallback(TSFTextStore* text_store) - : TSFTextStoreTestCallback(text_store) { - } + : TSFTextStoreTestCallback(text_store) {} HRESULT ReadLockGranted(DWORD flags) { const wchar_t kBuffer[] = L"0123456789"; @@ -865,8 +884,9 @@ class InsertTextAtSelectionTestCallback : public TSFTextStoreTestCallback { GetSelectionTest(2, 5); InsertTextAtSelectionQueryOnlyTest(kBuffer, 0, 2, 5); - LONG start, end; - TS_TEXTCHANGE change; + LONG start = 0; + LONG end = 0; + TS_TEXTCHANGE change = {}; EXPECT_EQ(TS_E_NOLOCK, text_store_->InsertTextAtSelection(0, kBuffer, 10, &start, &end, &change)); @@ -908,6 +928,9 @@ class InsertTextAtSelectionTestCallback : public TSFTextStoreTestCallback { return S_OK; } + + private: + DISALLOW_COPY_AND_ASSIGN(InsertTextAtSelectionTestCallback); }; TEST_F(TSFTextStoreTest, InsertTextAtSelectionTest) { @@ -919,16 +942,18 @@ TEST_F(TSFTextStoreTest, InsertTextAtSelectionTest) { Invoke(&callback, &InsertTextAtSelectionTestCallback::ReadWriteLockGranted)); - HRESULT result; + HRESULT result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result)); + EXPECT_EQ(S_OK, result); + result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); + EXPECT_EQ(S_OK, result); } class ScenarioTestCallback : public TSFTextStoreTestCallback { public: explicit ScenarioTestCallback(TSFTextStore* text_store) - : TSFTextStoreTestCallback(text_store) { - } + : TSFTextStoreTestCallback(text_store) {} HRESULT LockGranted1(DWORD flags) { SetSelectionTest(0, 0, S_OK); @@ -1023,6 +1048,9 @@ class ScenarioTestCallback : public TSFTextStoreTestCallback { EXPECT_EQ(0, composition.selection.end()); EXPECT_EQ(0, composition.underlines.size()); } + + private: + DISALLOW_COPY_AND_ASSIGN(ScenarioTestCallback); }; TEST_F(TSFTextStoreTest, ScenarioTest) { @@ -1053,24 +1081,28 @@ TEST_F(TSFTextStoreTest, ScenarioTest) { EXPECT_CALL(*sink_, OnTextChange(_, _)) .WillOnce(Return(S_OK)); - HRESULT result; + HRESULT result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); + EXPECT_EQ(S_OK, result); + result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); + EXPECT_EQ(S_OK, result); + result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); + EXPECT_EQ(S_OK, result); } class GetTextExtTestCallback : public TSFTextStoreTestCallback { public: explicit GetTextExtTestCallback(TSFTextStore* text_store) : TSFTextStoreTestCallback(text_store), - layout_prepared_character_num_(0) { - } + layout_prepared_character_num_(0) {} HRESULT LockGranted(DWORD flags) { SetInternalState(L"0123456789012", 0, 0, 0); layout_prepared_character_num_ = 13; - TsViewCookie view_cookie; + TsViewCookie view_cookie = 0; EXPECT_EQ(S_OK, text_store_->GetActiveView(&view_cookie)); GetTextExtTest(view_cookie, 0, 0, 11, 12, 11, 20); GetTextExtTest(view_cookie, 0, 1, 11, 12, 20, 20); @@ -1125,6 +1157,8 @@ class GetTextExtTestCallback : public TSFTextStoreTestCallback { private: uint32 layout_prepared_character_num_; + + DISALLOW_COPY_AND_ASSIGN(GetTextExtTestCallback); }; TEST_F(TSFTextStoreTest, GetTextExtTest) { @@ -1141,8 +1175,80 @@ TEST_F(TSFTextStoreTest, GetTextExtTest) { EXPECT_CALL(*sink_, OnLockGranted(_)) .WillOnce(Invoke(&callback, &GetTextExtTestCallback::LockGranted)); - HRESULT result; + HRESULT result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result)); + EXPECT_EQ(S_OK, result); +} + +TEST_F(TSFTextStoreTest, RequestSupportedAttrs) { + EXPECT_CALL(text_input_client_, GetTextInputType()) + .WillRepeatedly(Return(TEXT_INPUT_TYPE_TEXT)); + EXPECT_CALL(text_input_client_, GetTextInputMode()) + .WillRepeatedly(Return(TEXT_INPUT_MODE_DEFAULT)); + + EXPECT_HRESULT_FAILED(text_store_->RequestSupportedAttrs(0, 1, NULL)); + + const TS_ATTRID kUnknownAttributes[] = {GUID_NULL}; + EXPECT_HRESULT_FAILED(text_store_->RequestSupportedAttrs( + 0, arraysize(kUnknownAttributes), kUnknownAttributes)) + << "Must fail for unknown attributes"; + + const TS_ATTRID kAttributes[] = {GUID_NULL, GUID_PROP_INPUTSCOPE, GUID_NULL}; + EXPECT_EQ(S_OK, text_store_->RequestSupportedAttrs( + 0, arraysize(kAttributes), kAttributes)) + << "InputScope must be supported"; + + { + SCOPED_TRACE("Check if RequestSupportedAttrs fails while focus is lost"); + // Emulate focus lost + text_store_->SetFocusedTextInputClient(NULL, NULL); + EXPECT_HRESULT_FAILED(text_store_->RequestSupportedAttrs(0, 0, NULL)); + EXPECT_HRESULT_FAILED(text_store_->RequestSupportedAttrs( + 0, arraysize(kAttributes), kAttributes)); + } } +TEST_F(TSFTextStoreTest, RetrieveRequestedAttrs) { + EXPECT_CALL(text_input_client_, GetTextInputType()) + .WillRepeatedly(Return(TEXT_INPUT_TYPE_TEXT)); + EXPECT_CALL(text_input_client_, GetTextInputMode()) + .WillRepeatedly(Return(TEXT_INPUT_MODE_DEFAULT)); + + ULONG num_copied = 0xfffffff; + EXPECT_HRESULT_FAILED(text_store_->RetrieveRequestedAttrs( + 1, NULL, &num_copied)); + + { + SCOPED_TRACE("Make sure if InputScope is supported"); + TS_ATTRVAL buffer[2] = {}; + num_copied = 0xfffffff; + ASSERT_EQ(S_OK, text_store_->RetrieveRequestedAttrs( + arraysize(buffer), buffer, &num_copied)); + bool input_scope_found = false; + for (size_t i = 0; i < num_copied; ++i) { + base::win::ScopedVariant variant; + // Move ownership from |buffer[i].varValue| to |variant|. + std::swap(*variant.Receive(), buffer[i].varValue); + if (IsEqualGUID(buffer[i].idAttr, GUID_PROP_INPUTSCOPE)) { + EXPECT_EQ(VT_UNKNOWN, variant.type()); + base::win::ScopedComPtr<ITfInputScope> input_scope; + EXPECT_HRESULT_SUCCEEDED(input_scope.QueryFrom((&variant)->punkVal)); + input_scope_found = true; + // we do not break here to clean up all the retrieved VARIANTs. + } + } + EXPECT_TRUE(input_scope_found); + } + { + SCOPED_TRACE("Check if RetrieveRequestedAttrs fails while focus is lost"); + // Emulate focus lost + text_store_->SetFocusedTextInputClient(NULL, NULL); + num_copied = 0xfffffff; + TS_ATTRVAL buffer[2] = {}; + EXPECT_HRESULT_FAILED(text_store_->RetrieveRequestedAttrs( + arraysize(buffer), buffer, &num_copied)); + } +} + +} // namespace } // namespace ui diff --git a/chromium/ui/base/keycodes/OWNERS b/chromium/ui/base/keycodes/OWNERS index 7dc2fa7ba07..a49314c396b 100644 --- a/chromium/ui/base/keycodes/OWNERS +++ b/chromium/ui/base/keycodes/OWNERS @@ -1,2 +1,2 @@ -per-file usb_keycode_map*=garykac@chromium.org -per-file usb_keycode_map*=wez@chromium.org +garykac@chromium.org +wez@chromium.org diff --git a/chromium/ui/base/keycodes/keyboard_code_conversion_android.h b/chromium/ui/base/keycodes/keyboard_code_conversion_android.h deleted file mode 100644 index 8bf27899e93..00000000000 --- a/chromium/ui/base/keycodes/keyboard_code_conversion_android.h +++ /dev/null @@ -1,17 +0,0 @@ -// 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. - -#ifndef UI_BASE_KEYCODES_KEYBOARD_CODE_CONVERSION_ANDROID_H_ -#define UI_BASE_KEYCODES_KEYBOARD_CODE_CONVERSION_ANDROID_H_ - -#include "ui/base/keycodes/keyboard_codes_posix.h" -#include "ui/base/ui_export.h" - -namespace ui { - -UI_EXPORT KeyboardCode KeyboardCodeFromAndroidKeyCode(int keycode); - -} // namespace ui - -#endif // UI_BASE_KEYCODES_KEYBOARD_CODE_CONVERSION_ANDROID_H_ diff --git a/chromium/ui/base/keycodes/keyboard_code_conversion_win.h b/chromium/ui/base/keycodes/keyboard_code_conversion_win.h deleted file mode 100644 index 1cf91de3729..00000000000 --- a/chromium/ui/base/keycodes/keyboard_code_conversion_win.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef UI_BASE_KEYCODES_KEYBOARD_CODE_CONVERSION_WIN_H_ -#define UI_BASE_KEYCODES_KEYBOARD_CODE_CONVERSION_WIN_H_ - -#include "ui/base/keycodes/keyboard_codes.h" -#include "ui/base/ui_export.h" - -namespace ui { - -// Methods to convert ui::KeyboardCode/Windows virtual key type methods. -UI_EXPORT WORD WindowsKeyCodeForKeyboardCode(KeyboardCode keycode); -UI_EXPORT KeyboardCode KeyboardCodeForWindowsKeyCode(WORD keycode); - -} // namespace ui - -#endif // UI_BASE_KEYCODES_KEYBOARD_CODE_CONVERSION_WIN_H_ diff --git a/chromium/ui/base/keycodes/keyboard_code_conversion_x.h b/chromium/ui/base/keycodes/keyboard_code_conversion_x.h deleted file mode 100644 index f394de17b9b..00000000000 --- a/chromium/ui/base/keycodes/keyboard_code_conversion_x.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef UI_BASE_KEYCODES_KEYBOARD_CODE_CONVERSION_X_H_ -#define UI_BASE_KEYCODES_KEYBOARD_CODE_CONVERSION_X_H_ - -#include "base/basictypes.h" -#include "ui/base/keycodes/keyboard_codes_posix.h" -#include "ui/base/ui_export.h" - -typedef union _XEvent XEvent; - -namespace ui { - -UI_EXPORT KeyboardCode KeyboardCodeFromXKeyEvent(XEvent* xev); - -UI_EXPORT KeyboardCode KeyboardCodeFromXKeysym(unsigned int keysym); - -// Returns a character on a standard US PC keyboard from an XEvent. -UI_EXPORT uint16 GetCharacterFromXEvent(XEvent* xev); - -// Converts a KeyboardCode into an X KeySym. -UI_EXPORT int XKeysymForWindowsKeyCode(KeyboardCode keycode, bool shift); - -// Converts an X keycode into an X KeySym. -unsigned int DefaultXKeysymFromHardwareKeycode(unsigned int keycode); - -} // namespace ui - -#endif // UI_BASE_KEYCODES_KEYBOARD_CODE_CONVERSION_X_H_ diff --git a/chromium/ui/base/keycodes/keycode_converter.cc b/chromium/ui/base/keycodes/keycode_converter.cc new file mode 100644 index 00000000000..a7010aaca2d --- /dev/null +++ b/chromium/ui/base/keycodes/keycode_converter.cc @@ -0,0 +1,115 @@ +// Copyright (c) 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 "ui/base/keycodes/keycode_converter.h" + +namespace ui { + +namespace { + +#if defined(OS_WIN) +#define USB_KEYMAP(usb, xkb, win, mac, code) {usb, win, code} +#elif defined(OS_LINUX) +#define USB_KEYMAP(usb, xkb, win, mac, code) {usb, xkb, code} +#elif defined(OS_MACOSX) +#define USB_KEYMAP(usb, xkb, win, mac, code) {usb, mac, code} +#else +#define USB_KEYMAP(usb, xkb, win, mac, code) {usb, 0, code} +#endif +#include "ui/base/keycodes/keycode_converter_data.h" + +const size_t kKeycodeMapEntries = arraysize(usb_keycode_map); + +} // namespace + +KeycodeConverter::KeycodeConverter() { +} + +KeycodeConverter* KeycodeConverter::GetInstance() { + return Singleton<KeycodeConverter>::get(); +} + +size_t KeycodeConverter::NumKeycodeMapEntriesForTest() { + return kKeycodeMapEntries; +} + +const KeycodeMapEntry* KeycodeConverter::GetKeycodeMapForTest() { + return &usb_keycode_map[0]; +} + +uint16_t KeycodeConverter::InvalidNativeKeycode() { + return usb_keycode_map[0].native_keycode; +} + +const char* KeycodeConverter::InvalidKeyboardEventCode() { + return "Unidentified"; +} + +const char* KeycodeConverter::NativeKeycodeToCode(uint16_t native_keycode) { + for (size_t i = 0; i < kKeycodeMapEntries; ++i) { + if (usb_keycode_map[i].native_keycode == native_keycode) { + if (usb_keycode_map[i].code != NULL) + return usb_keycode_map[i].code; + break; + } + } + return InvalidKeyboardEventCode(); +} + +uint16_t KeycodeConverter::CodeToNativeKeycode(const char* code) { + if (!code || + strcmp(code, InvalidKeyboardEventCode()) == 0) { + return InvalidNativeKeycode(); + } + + for (size_t i = 0; i < kKeycodeMapEntries; ++i) { + if (usb_keycode_map[i].code && + strcmp(usb_keycode_map[i].code, code) == 0) { + return usb_keycode_map[i].native_keycode; + } + } + return InvalidNativeKeycode(); +} + +// USB keycodes +// Note that USB keycodes are not part of any web standard. +// Please don't use USB keycodes in new code. + +uint16_t KeycodeConverter::InvalidUsbKeycode() { + return usb_keycode_map[0].usb_keycode; +} + +uint16_t KeycodeConverter::UsbKeycodeToNativeKeycode(uint32_t usb_keycode) { + // Deal with some special-cases that don't fit the 1:1 mapping. + if (usb_keycode == 0x070032) // non-US hash. + usb_keycode = 0x070031; // US backslash. +#if defined(OS_MACOSX) + if (usb_keycode == 0x070046) // PrintScreen. + usb_keycode = 0x070068; // F13. +#endif + + for (size_t i = 0; i < kKeycodeMapEntries; ++i) { + if (usb_keycode_map[i].usb_keycode == usb_keycode) + return usb_keycode_map[i].native_keycode; + } + return InvalidNativeKeycode(); +} + +uint32_t KeycodeConverter::NativeKeycodeToUsbKeycode(uint16_t native_keycode) { + for (size_t i = 0; i < kKeycodeMapEntries; ++i) { + if (usb_keycode_map[i].native_keycode == native_keycode) + return usb_keycode_map[i].usb_keycode; + } + return InvalidUsbKeycode(); +} + +const char* KeycodeConverter::UsbKeycodeToCode(uint32_t usb_keycode) { + for (size_t i = 0; i < kKeycodeMapEntries; ++i) { + if (usb_keycode_map[i].usb_keycode == usb_keycode) + return usb_keycode_map[i].code; + } + return InvalidKeyboardEventCode(); +} + +} // namespace ui diff --git a/chromium/ui/base/keycodes/keycode_converter.h b/chromium/ui/base/keycodes/keycode_converter.h new file mode 100644 index 00000000000..cd9ac431574 --- /dev/null +++ b/chromium/ui/base/keycodes/keycode_converter.h @@ -0,0 +1,87 @@ +// Copyright (c) 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. + +#ifndef UI_BASE_KEYCODES_KEYCODE_CONVERTER_H_ +#define UI_BASE_KEYCODES_KEYCODE_CONVERTER_H_ + +#include <stdint.h> +#include "base/basictypes.h" +#include "base/memory/singleton.h" + +// For reference, the W3C UI Event spec is located at: +// http://www.w3.org/TR/uievents/ + +namespace ui { + +// This structure is used to define the keycode mapping table. +// It is defined here because the unittests need access to it. +typedef struct { + // USB keycode: + // Upper 16-bits: USB Usage Page. + // Lower 16-bits: USB Usage Id: Assigned ID within this usage page. + uint32_t usb_keycode; + + // Contains one of the following: + // On Linux: XKB scancode + // On Windows: Windows OEM scancode + // On Mac: Mac keycode + uint16_t native_keycode; + + // The UIEvents (aka: DOM4Events) |code| value as defined in: + // https://dvcs.w3.org/hg/d4e/raw-file/tip/source_respec.htm + const char* code; +} KeycodeMapEntry; + +// A class to convert between the current platform's native keycode (scancode) +// and platform-neutral |code| values (as defined in the W3C UI Events +// spec (http://www.w3.org/TR/uievents/). +class KeycodeConverter { + public: + static KeycodeConverter* GetInstance(); + + // Return the value that identifies an invalid native keycode. + uint16_t InvalidNativeKeycode(); + + // Return the string that indentifies an invalid UI Event |code|. + // The returned pointer references a static global string. + const char* InvalidKeyboardEventCode(); + + // Convert a native (Mac/Win/Linux) keycode into the |code| string. + // The returned pointer references a static global string. + const char* NativeKeycodeToCode(uint16_t native_keycode); + + // Convert a UI Events |code| string value into a native keycode. + uint16_t CodeToNativeKeycode(const char* code); + + // The following methods relate to USB keycodes. + // Note that USB keycodes are not part of any web standard. + // Please don't use USB keycodes in new code. + + // Return the value that identifies an invalid USB keycode. + uint16_t InvalidUsbKeycode(); + + // Convert a USB keycode into an equivalent platform native keycode. + uint16_t UsbKeycodeToNativeKeycode(uint32_t usb_keycode); + + // Convert a platform native keycode into an equivalent USB keycode. + uint32_t NativeKeycodeToUsbKeycode(uint16_t native_keycode); + + // Convert a USB keycode into the string with the UI Event |code| value. + // The returned pointer references a static global string. + const char* UsbKeycodeToCode(uint32_t usb_keycode); + + // Static methods to support testing. + size_t NumKeycodeMapEntriesForTest(); + const KeycodeMapEntry* GetKeycodeMapForTest(); + + private: + KeycodeConverter(); + friend struct DefaultSingletonTraits<KeycodeConverter>; + + DISALLOW_COPY_AND_ASSIGN(KeycodeConverter); +}; + +} // namespace ui + +#endif // UI_BASE_KEYCODE_CONVERTER_H_ diff --git a/chromium/ui/base/keycodes/keycode_converter_data.h b/chromium/ui/base/keycodes/keycode_converter_data.h new file mode 100644 index 00000000000..d7788e5ba97 --- /dev/null +++ b/chromium/ui/base/keycodes/keycode_converter_data.h @@ -0,0 +1,379 @@ +// Copyright (c) 2012 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. + +#ifndef UI_BASE_KEYCODES_KEYCODE_CONVERTER_DATA_H_ +#define UI_BASE_KEYCODES_KEYCODE_CONVERTER_DATA_H_ + +// Data in this file was created by referencing: +// USB HID Usage Tables (v1.11) 27 June 2001 +// HIToolbox/Events.h (Mac) + +const KeycodeMapEntry usb_keycode_map[] = { + + // USB XKB Win Mac Code + USB_KEYMAP(0x000000, 0x0000, 0x0000, 0xffff, NULL), // Invalid + + // ========================================= + // USB Usage Page 0x01: Generic Desktop Page + // ========================================= + + // Sleep could be encoded as USB#0c0032, but there's no corresponding WakeUp + // in the 0x0c USB page. + + // USB XKB Win Mac + USB_KEYMAP(0x010082, 0x0096, 0x0000, 0xffff, NULL), // SystemSleep + USB_KEYMAP(0x010083, 0x0097, 0x0000, 0xffff, NULL), // SystemWakeUp + + // ========================================= + // USB Usage Page 0x07: Keyboard/Keypad Page + // ========================================= + + // TODO(garykac): + // XKB#005c ISO Level3 Shift (AltGr) + // XKB#005e <>|| + // XKB#006d Linefeed + // XKB#008a SunProps cf. USB#0700a3 CrSel/Props + // XKB#008e SunOpen + // Mac#003f kVK_Function + // Mac#000a kVK_ISO_Section (ISO keyboards only) + // Mac#0066 kVK_JIS_Eisu (USB#07008a Henkan?) + + // USB XKB Win Mac + USB_KEYMAP(0x070000, 0x0000, 0x0000, 0xffff, NULL), // Reserved + USB_KEYMAP(0x070001, 0x0000, 0x0000, 0xffff, NULL), // ErrorRollOver + USB_KEYMAP(0x070002, 0x0000, 0x0000, 0xffff, NULL), // POSTFail + USB_KEYMAP(0x070003, 0x0000, 0x0000, 0xffff, NULL), // ErrorUndefined + USB_KEYMAP(0x070004, 0x0026, 0x001e, 0x0000, "KeyA"), // aA + USB_KEYMAP(0x070005, 0x0038, 0x0030, 0x000b, "KeyB"), // bB + USB_KEYMAP(0x070006, 0x0036, 0x002e, 0x0008, "KeyC"), // cC + USB_KEYMAP(0x070007, 0x0028, 0x0020, 0x0002, "KeyD"), // dD + + USB_KEYMAP(0x070008, 0x001a, 0x0012, 0x000e, "KeyE"), // eEo + USB_KEYMAP(0x070009, 0x0029, 0x0021, 0x0003, "KeyF"), // fF + USB_KEYMAP(0x07000a, 0x002a, 0x0022, 0x0005, "KeyG"), // gG + USB_KEYMAP(0x07000b, 0x002b, 0x0023, 0x0004, "KeyH"), // hH + USB_KEYMAP(0x07000c, 0x001f, 0x0017, 0x0022, "KeyI"), // iI + USB_KEYMAP(0x07000d, 0x002c, 0x0024, 0x0026, "KeyJ"), // jJ + USB_KEYMAP(0x07000e, 0x002d, 0x0025, 0x0028, "KeyK"), // kK + USB_KEYMAP(0x07000f, 0x002e, 0x0026, 0x0025, "KeyL"), // lL + + USB_KEYMAP(0x070010, 0x003a, 0x0032, 0x002e, "KeyM"), // mM + USB_KEYMAP(0x070011, 0x0039, 0x0031, 0x002d, "KeyN"), // nN + USB_KEYMAP(0x070012, 0x0020, 0x0018, 0x001f, "KeyO"), // oO + USB_KEYMAP(0x070013, 0x0021, 0x0019, 0x0023, "KeyP"), // pP + USB_KEYMAP(0x070014, 0x0018, 0x0010, 0x000c, "KeyQ"), // qQ + USB_KEYMAP(0x070015, 0x001b, 0x0013, 0x000f, "KeyR"), // rR + USB_KEYMAP(0x070016, 0x0027, 0x001f, 0x0001, "KeyS"), // sS + USB_KEYMAP(0x070017, 0x001c, 0x0014, 0x0011, "KeyT"), // tT + + USB_KEYMAP(0x070018, 0x001e, 0x0016, 0x0020, "KeyU"), // uU + USB_KEYMAP(0x070019, 0x0037, 0x002f, 0x0009, "KeyV"), // vV + USB_KEYMAP(0x07001a, 0x0019, 0x0011, 0x000d, "KeyW"), // wW + USB_KEYMAP(0x07001b, 0x0035, 0x002d, 0x0007, "KeyX"), // xX + USB_KEYMAP(0x07001c, 0x001d, 0x0015, 0x0010, "KeyY"), // yY + USB_KEYMAP(0x07001d, 0x0034, 0x002c, 0x0006, "KeyZ"), // zZ + USB_KEYMAP(0x07001e, 0x000a, 0x0002, 0x0012, "Digit1"), // 1! + USB_KEYMAP(0x07001f, 0x000b, 0x0003, 0x0013, "Digit2"), // 2@ + + USB_KEYMAP(0x070020, 0x000c, 0x0004, 0x0014, "Digit3"), // 3# + USB_KEYMAP(0x070021, 0x000d, 0x0005, 0x0015, "Digit4"), // 4$ + USB_KEYMAP(0x070022, 0x000e, 0x0006, 0x0017, "Digit5"), // 5% + USB_KEYMAP(0x070023, 0x000f, 0x0007, 0x0016, "Digit6"), // 6^ + USB_KEYMAP(0x070024, 0x0010, 0x0008, 0x001a, "Digit7"), // 7& + USB_KEYMAP(0x070025, 0x0011, 0x0009, 0x001c, "Digit8"), // 8* + USB_KEYMAP(0x070026, 0x0012, 0x000a, 0x0019, "Digit9"), // 9( + USB_KEYMAP(0x070027, 0x0013, 0x000b, 0x001d, "Digit0"), // 0) + + USB_KEYMAP(0x070028, 0x0024, 0x001c, 0x0024, "Enter"), + USB_KEYMAP(0x070029, 0x0009, 0x0001, 0x0035, "Escape"), + USB_KEYMAP(0x07002a, 0x0016, 0x000e, 0x0033, "Backspace"), + USB_KEYMAP(0x07002b, 0x0017, 0x000f, 0x0030, "Tab"), + USB_KEYMAP(0x07002c, 0x0041, 0x0039, 0x0031, "Space"), // Spacebar + USB_KEYMAP(0x07002d, 0x0014, 0x000c, 0x001b, "Minus"), // -_ + USB_KEYMAP(0x07002e, 0x0015, 0x000d, 0x0018, "Equal"), // =+ + USB_KEYMAP(0x07002f, 0x0022, 0x001a, 0x0021, "BracketLeft"),// [{ + + USB_KEYMAP(0x070030, 0x0023, 0x001b, 0x001e, "BracketRight"), // ]} + USB_KEYMAP(0x070031, 0x0033, 0x002b, 0x002a, "Backslash"), // \| (US keyboard only) + // USB#070032 never appears on keyboards that have USB#070031. + // Platforms use the same scancode as for the two keys. + // The keycap varies on international keyboards: + // Dan: '* Dutch: <> Ger: #' UK: #~ + // TODO(garykac): Verify Mac intl keyboard. + //USB_KEYMAP(0x070032, 0x0033, 0x002b, 0x002a, "IntlHash"), // #~ (Non-US) + USB_KEYMAP(0x070033, 0x002f, 0x0027, 0x0029, "Semicolon"), // ;: + USB_KEYMAP(0x070034, 0x0030, 0x0028, 0x0027, "Quote"), // '" + USB_KEYMAP(0x070035, 0x0031, 0x0029, 0x0032, "Backquote"), // `~ + USB_KEYMAP(0x070036, 0x003b, 0x0033, 0x002b, "Comma"), // ,< + USB_KEYMAP(0x070037, 0x003c, 0x0034, 0x002f, "Period"), // .> + + USB_KEYMAP(0x070038, 0x003d, 0x0035, 0x002c, "Slash"), // /? + // TODO(garykac): CapsLock requires special handling for each platform. + USB_KEYMAP(0x070039, 0x0042, 0x003a, 0x0039, "CapsLock"), + USB_KEYMAP(0x07003a, 0x0043, 0x003b, 0x007a, "F1"), + USB_KEYMAP(0x07003b, 0x0044, 0x003c, 0x0078, "F2"), + USB_KEYMAP(0x07003c, 0x0045, 0x003d, 0x0063, "F3"), + USB_KEYMAP(0x07003d, 0x0046, 0x003e, 0x0076, "F4"), + USB_KEYMAP(0x07003e, 0x0047, 0x003f, 0x0060, "F5"), + USB_KEYMAP(0x07003f, 0x0048, 0x0040, 0x0061, "F6"), + + USB_KEYMAP(0x070040, 0x0049, 0x0041, 0x0062, "F7"), + USB_KEYMAP(0x070041, 0x004a, 0x0042, 0x0064, "F8"), + USB_KEYMAP(0x070042, 0x004b, 0x0043, 0x0065, "F9"), + USB_KEYMAP(0x070043, 0x004c, 0x0044, 0x006d, "F10"), + USB_KEYMAP(0x070044, 0x005f, 0x0057, 0x0067, "F11"), + USB_KEYMAP(0x070045, 0x0060, 0x0058, 0x006f, "F12"), + // PrintScreen is effectively F13 on Mac OS X. + USB_KEYMAP(0x070046, 0x006b, 0xe037, 0xffff, "PrintScreen"), + USB_KEYMAP(0x070047, 0x004e, 0x0046, 0xffff, "ScrollLock"), + + USB_KEYMAP(0x070048, 0x007f, 0x0000, 0xffff, "Pause"), + // Labeled "Help/Insert" on Mac. + USB_KEYMAP(0x070049, 0x0076, 0xe052, 0x0072, "Insert"), + USB_KEYMAP(0x07004a, 0x006e, 0xe047, 0x0073, "Home"), + USB_KEYMAP(0x07004b, 0x0070, 0xe049, 0x0074, "PageUp"), + // Delete (Forward Delete) + USB_KEYMAP(0x07004c, 0x0077, 0xe053, 0x0075, "Delete"), + USB_KEYMAP(0x07004d, 0x0073, 0xe04f, 0x0077, "End"), + USB_KEYMAP(0x07004e, 0x0075, 0xe051, 0x0079, "PageDown"), + USB_KEYMAP(0x07004f, 0x0072, 0xe04d, 0x007c, "ArrowRight"), + + USB_KEYMAP(0x070050, 0x0071, 0xe04b, 0x007b, "ArrowLeft"), + USB_KEYMAP(0x070051, 0x0074, 0xe050, 0x007d, "ArrowDown"), + USB_KEYMAP(0x070052, 0x006f, 0xe048, 0x007e, "ArrowUp"), + USB_KEYMAP(0x070053, 0x004d, 0x0045, 0x0047, "NumLock"), // Keypad_NumLock Clear + USB_KEYMAP(0x070054, 0x006a, 0xe035, 0x004b, "NumpadDivide"), // Keypad_/ + USB_KEYMAP(0x070055, 0x003f, 0x0037, 0x0043, "NumpadMultiply"),// Keypad_* + USB_KEYMAP(0x070056, 0x0052, 0x004a, 0x004e, "NumpadSubtract"),// Keypad_- + USB_KEYMAP(0x070057, 0x0056, 0x004e, 0x0045, "NumpadAdd"), // Keypad_+ + + USB_KEYMAP(0x070058, 0x0068, 0xe01c, 0x004c, "NumpadEnter"), // Keypad_Enter + USB_KEYMAP(0x070059, 0x0057, 0x004f, 0x0053, "Numpad1"), // Keypad_1 End + USB_KEYMAP(0x07005a, 0x0058, 0x0050, 0x0054, "Numpad2"), // Keypad_2 DownArrow + USB_KEYMAP(0x07005b, 0x0059, 0x0051, 0x0055, "Numpad3"), // Keypad_3 PageDown + USB_KEYMAP(0x07005c, 0x0053, 0x004b, 0x0056, "Numpad4"), // Keypad_4 LeftArrow + USB_KEYMAP(0x07005d, 0x0054, 0x004c, 0x0057, "Numpad5"), // Keypad_5 + USB_KEYMAP(0x07005e, 0x0055, 0x004d, 0x0058, "Numpad6"), // Keypad_6 RightArrow + USB_KEYMAP(0x07005f, 0x004f, 0x0047, 0x0059, "Numpad7"), // Keypad_7 Home + + USB_KEYMAP(0x070060, 0x0050, 0x0048, 0x005b, "Numpad8"), // Keypad_8 UpArrow + USB_KEYMAP(0x070061, 0x0051, 0x0049, 0x005c, "Numpad9"), // Keypad_9 PageUp + USB_KEYMAP(0x070062, 0x005a, 0x0052, 0x0052, "Numpad0"), // Keypad_0 Insert + USB_KEYMAP(0x070063, 0x005b, 0x0053, 0x0041, "NumpadDecimal"), // Keypad_. Delete + // USB#070064 is not present on US keyboard. + // This key is typically located near LeftShift key. + // The keycap varies on international keyboards: + // Dan: <> Dutch: ][ Ger: <> UK: \| + USB_KEYMAP(0x070064, 0x005e, 0x0056, 0x000a, "IntlBackslash"), // Non-US \| + // AppMenu (next to RWin key) + USB_KEYMAP(0x070065, 0x0087, 0xe05d, 0x006e, "ContextMenu"), + USB_KEYMAP(0x070066, 0x007c, 0x0000, 0xffff, "Power"), + USB_KEYMAP(0x070067, 0x007d, 0x0000, 0x0051, "NumpadEqual"), // Keypad_= + + USB_KEYMAP(0x070068, 0x0000, 0x005b, 0x0069, "F13"), + USB_KEYMAP(0x070069, 0x0000, 0x005c, 0x006b, "F14"), + USB_KEYMAP(0x07006a, 0x0000, 0x005d, 0x0071, "F15"), + USB_KEYMAP(0x07006b, 0x0000, 0x0063, 0x006a, "F16"), + USB_KEYMAP(0x07006c, 0x0000, 0x0064, 0x0040, "F17"), + USB_KEYMAP(0x07006d, 0x0000, 0x0065, 0x004f, "F18"), + USB_KEYMAP(0x07006e, 0x0000, 0x0066, 0x0050, "F19"), + USB_KEYMAP(0x07006f, 0x0000, 0x0067, 0x005a, "F20"), + + USB_KEYMAP(0x070070, 0x0000, 0x0068, 0xffff, "F21"), + USB_KEYMAP(0x070071, 0x0000, 0x0069, 0xffff, "F22"), + USB_KEYMAP(0x070072, 0x0000, 0x006a, 0xffff, "F23"), + USB_KEYMAP(0x070073, 0x0000, 0x006b, 0xffff, "F24"), + USB_KEYMAP(0x070074, 0x0000, 0x0000, 0xffff, NULL), // Execute + USB_KEYMAP(0x070075, 0x0092, 0xe03b, 0xffff, "Help"), + USB_KEYMAP(0x070076, 0x0093, 0x0000, 0xffff, NULL), // Menu + //USB_KEYMAP(0x070077, 0x0000, 0x0000, 0xffff, NULL), // Select + + //USB_KEYMAP(0x070078, 0x0000, 0x0000, 0xffff, NULL), // Stop + USB_KEYMAP(0x070079, 0x0089, 0x0000, 0xffff, NULL), // Again (Redo) + USB_KEYMAP(0x07007a, 0x008b, 0xe008, 0xffff, "Undo"), + USB_KEYMAP(0x07007b, 0x0091, 0xe017, 0xffff, "Cut"), + USB_KEYMAP(0x07007c, 0x008d, 0xe018, 0xffff, "Copy"), + USB_KEYMAP(0x07007d, 0x008f, 0xe00a, 0xffff, "Paste"), + USB_KEYMAP(0x07007e, 0x0090, 0x0000, 0xffff, NULL), // Find + USB_KEYMAP(0x07007f, 0x0079, 0xe020, 0x004a, "VolumeMute"), + + USB_KEYMAP(0x070080, 0x007b, 0xe030, 0x0048, "VolumeUp"), + USB_KEYMAP(0x070081, 0x007a, 0xe02e, 0x0049, "VolumeDown"), + //USB_KEYMAP(0x070082, 0x0000, 0x0000, 0xffff, NULL), // LockingCapsLock + //USB_KEYMAP(0x070083, 0x0000, 0x0000, 0xffff, NULL), // LockingNumLock + //USB_KEYMAP(0x070084, 0x0000, 0x0000, 0xffff, NULL), // LockingScrollLock + // USB#070085 is used as Brazilian Keypad_. + USB_KEYMAP(0x070085, 0x0000, 0x0000, 0x005f, "NumpadComma"), // Keypad_Comma + + // International1 + // USB#070086 is used on AS/400 keyboards. Standard Keypad_= is USB#070067. + //USB_KEYMAP(0x070086, 0x0000, 0x0000, 0xffff, NULL), // Keypad_= + // USB#070087 is used for Brazilian /? and Japanese _ 'ro'. + USB_KEYMAP(0x070087, 0x0061, 0x0000, 0x005e, "IntlRo"), + // International2 + // USB#070088 is used as Japanese Hiragana/Katakana key. + USB_KEYMAP(0x070088, 0x0065, 0x0000, 0x0068, "KanaMode"), + // International3 + // USB#070089 is used as Japanese Yen key. + USB_KEYMAP(0x070089, 0x0084, 0x007d, 0x005d, "IntlYen"), + // International4 + // USB#07008a is used as Japanese Henkan (Convert) key. + USB_KEYMAP(0x07008a, 0x0064, 0x0000, 0xffff, "Convert"), + // International5 + // USB#07008b is used as Japanese Muhenkan (No-convert) key. + USB_KEYMAP(0x07008b, 0x0066, 0x0000, 0xffff, "NoConvert"), + //USB_KEYMAP(0x07008c, 0x0000, 0x0000, 0xffff, NULL), // International6 + //USB_KEYMAP(0x07008d, 0x0000, 0x0000, 0xffff, NULL), // International7 + //USB_KEYMAP(0x07008e, 0x0000, 0x0000, 0xffff, NULL), // International8 + //USB_KEYMAP(0x07008f, 0x0000, 0x0000, 0xffff, NULL), // International9 + + // LANG1 + // USB#070090 is used as Korean Hangul/English toggle key. + USB_KEYMAP(0x070090, 0x0082, 0x0000, 0xffff, "HangulMode"), + // LANG2 + // USB#070091 is used as Korean Hanja conversion key. + USB_KEYMAP(0x070091, 0x0083, 0x0000, 0xffff, "Hanja"), + // LANG3 + // USB#070092 is used as Japanese Katakana key. + USB_KEYMAP(0x070092, 0x0062, 0x0000, 0xffff, NULL), + // LANG4 + // USB#070093 is used as Japanese Hiragana key. + USB_KEYMAP(0x070093, 0x0063, 0x0000, 0xffff, NULL), + // LANG5 + // USB#070094 is used as Japanese Zenkaku/Hankaku (Fullwidth/halfwidth) key. + //USB_KEYMAP(0x070094, 0x0000, 0x0000, 0xffff, NULL), + //USB_KEYMAP(0x070095, 0x0000, 0x0000, 0xffff, NULL), // LANG6 + //USB_KEYMAP(0x070096, 0x0000, 0x0000, 0xffff, NULL), // LANG7 + //USB_KEYMAP(0x070097, 0x0000, 0x0000, 0xffff, NULL), // LANG8 + //USB_KEYMAP(0x070098, 0x0000, 0x0000, 0xffff, NULL), // LANG9 + + //USB_KEYMAP(0x070099, 0x0000, 0x0000, 0xffff, NULL), // AlternateErase + //USB_KEYMAP(0x07009a, 0x0000, 0x0000, 0xffff, NULL), // SysReq/Attention + USB_KEYMAP(0x07009b, 0x0088, 0x0000, 0xffff, "Cancel"), + //USB_KEYMAP(0x07009c, 0x0000, 0x0000, 0xffff, NULL), // Clear + //USB_KEYMAP(0x07009d, 0x0000, 0x0000, 0xffff, NULL), // Prior + //USB_KEYMAP(0x07009e, 0x0000, 0x0000, 0xffff, NULL), // Return + //USB_KEYMAP(0x07009f, 0x0000, 0x0000, 0xffff, NULL), // Separator + + //USB_KEYMAP(0x0700a0, 0x0000, 0x0000, 0xffff, NULL), // Out + //USB_KEYMAP(0x0700a1, 0x0000, 0x0000, 0xffff, NULL), // Oper + //USB_KEYMAP(0x0700a2, 0x0000, 0x0000, 0xffff, NULL), // Clear/Again + //USB_KEYMAP(0x0700a3, 0x0000, 0x0000, 0xffff, NULL), // CrSel/Props + //USB_KEYMAP(0x0700a4, 0x0000, 0x0000, 0xffff, NULL), // ExSel + + //USB_KEYMAP(0x0700b0, 0x0000, 0x0000, 0xffff, NULL), // Keypad_00 + //USB_KEYMAP(0x0700b1, 0x0000, 0x0000, 0xffff, NULL), // Keypad_000 + //USB_KEYMAP(0x0700b2, 0x0000, 0x0000, 0xffff, NULL), // ThousandsSeparator + //USB_KEYMAP(0x0700b3, 0x0000, 0x0000, 0xffff, NULL), // DecimalSeparator + //USB_KEYMAP(0x0700b4, 0x0000, 0x0000, 0xffff, NULL), // CurrencyUnit + //USB_KEYMAP(0x0700b5, 0x0000, 0x0000, 0xffff, NULL), // CurrencySubunit + USB_KEYMAP(0x0700b6, 0x00bb, 0x0000, 0xffff, "NumpadParenLeft"), // Keypad_( + USB_KEYMAP(0x0700b7, 0x00bc, 0x0000, 0xffff, "NumpadParenRight"), // Keypad_) + + //USB_KEYMAP(0x0700b8, 0x0000, 0x0000, 0xffff, NULL), // Keypad_{ + //USB_KEYMAP(0x0700b9, 0x0000, 0x0000, 0xffff, NULL), // Keypad_} + //USB_KEYMAP(0x0700ba, 0x0000, 0x0000, 0xffff, NULL), // Keypad_Tab + //USB_KEYMAP(0x0700bb, 0x0000, 0x0000, 0xffff, NULL), // Keypad_Backspace + //USB_KEYMAP(0x0700bc, 0x0000, 0x0000, 0xffff, NULL), // Keypad_A + //USB_KEYMAP(0x0700bd, 0x0000, 0x0000, 0xffff, NULL), // Keypad_B + //USB_KEYMAP(0x0700be, 0x0000, 0x0000, 0xffff, NULL), // Keypad_C + //USB_KEYMAP(0x0700bf, 0x0000, 0x0000, 0xffff, NULL), // Keypad_D + + //USB_KEYMAP(0x0700c0, 0x0000, 0x0000, 0xffff, NULL), // Keypad_E + //USB_KEYMAP(0x0700c1, 0x0000, 0x0000, 0xffff, NULL), // Keypad_F + //USB_KEYMAP(0x0700c2, 0x0000, 0x0000, 0xffff, NULL), // Keypad_Xor + //USB_KEYMAP(0x0700c3, 0x0000, 0x0000, 0xffff, NULL), // Keypad_^ + //USB_KEYMAP(0x0700c4, 0x0000, 0x0000, 0xffff, NULL), // Keypad_% + //USB_KEYMAP(0x0700c5, 0x0000, 0x0000, 0xffff, NULL), // Keypad_< + //USB_KEYMAP(0x0700c6, 0x0000, 0x0000, 0xffff, NULL), // Keypad_> + //USB_KEYMAP(0x0700c7, 0x0000, 0x0000, 0xffff, NULL), // Keypad_& + + //USB_KEYMAP(0x0700c8, 0x0000, 0x0000, 0xffff, NULL), // Keypad_&& + //USB_KEYMAP(0x0700c9, 0x0000, 0x0000, 0xffff, NULL), // Keypad_| + //USB_KEYMAP(0x0700ca, 0x0000, 0x0000, 0xffff, NULL), // Keypad_|| + //USB_KEYMAP(0x0700cb, 0x0000, 0x0000, 0xffff, NULL), // Keypad_: + //USB_KEYMAP(0x0700cc, 0x0000, 0x0000, 0xffff, NULL), // Keypad_# + //USB_KEYMAP(0x0700cd, 0x0000, 0x0000, 0xffff, NULL), // Keypad_Space + //USB_KEYMAP(0x0700ce, 0x0000, 0x0000, 0xffff, NULL), // Keypad_@ + //USB_KEYMAP(0x0700cf, 0x0000, 0x0000, 0xffff, NULL), // Keypad_! + + //USB_KEYMAP(0x0700d0, 0x0000, 0x0000, 0xffff, NULL), // Keypad_MemoryStore + //USB_KEYMAP(0x0700d1, 0x0000, 0x0000, 0xffff, NULL), // Keypad_MemoryRecall + //USB_KEYMAP(0x0700d2, 0x0000, 0x0000, 0xffff, NULL), // Keypad_MemoryClear + //USB_KEYMAP(0x0700d3, 0x0000, 0x0000, 0xffff, NULL), // Keypad_MemoryAdd + //USB_KEYMAP(0x0700d4, 0x0000, 0x0000, 0xffff, NULL), // Keypad_MemorySubtract + //USB_KEYMAP(0x0700d5, 0x0000, 0x0000, 0xffff, NULL), // Keypad_MemoryMultiply + //USB_KEYMAP(0x0700d6, 0x0000, 0x0000, 0xffff, NULL), // Keypad_MemoryDivide + USB_KEYMAP(0x0700d7, 0x007e, 0x0000, 0xffff, "NumpadChangeSign"), // Keypad_+/- + + //USB_KEYMAP(0x0700d8, 0x0000, 0x0000, 0xffff, NULL), // Keypad_Clear + //USB_KEYMAP(0x0700d9, 0x0000, 0x0000, 0xffff, NULL), // Keypad_ClearEntry + //USB_KEYMAP(0x0700da, 0x0000, 0x0000, 0xffff, NULL), // Keypad_Binary + //USB_KEYMAP(0x0700db, 0x0000, 0x0000, 0xffff, NULL), // Keypad_Octal + USB_KEYMAP(0x0700dc, 0x0081, 0x0000, 0xffff, NULL), // Keypad_Decimal + //USB_KEYMAP(0x0700dd, 0x0000, 0x0000, 0xffff, NULL), // Keypad_Hexadecimal + // USB#0700de - #0700df are reserved. + + USB_KEYMAP(0x0700e0, 0x0025, 0x001d, 0x003b, "ControlLeft"), + USB_KEYMAP(0x0700e1, 0x0032, 0x002a, 0x0038, "ShiftLeft"), + USB_KEYMAP(0x0700e2, 0x0040, 0x0038, 0x003a, "AltLeft"), // LeftAlt/Option + USB_KEYMAP(0x0700e3, 0x0085, 0xe05b, 0x0037, "OSLeft"), // LeftGUI/Super/Win/Cmd + USB_KEYMAP(0x0700e4, 0x0069, 0xe01d, 0x003e, "ControlRight"), + USB_KEYMAP(0x0700e5, 0x003e, 0x0036, 0x003c, "ShiftRight"), + USB_KEYMAP(0x0700e6, 0x006c, 0xe038, 0x003d, "AltRight"), // RightAlt/Option + USB_KEYMAP(0x0700e7, 0x0086, 0xe05c, 0x0036, "OSRight"), // RightGUI/Super/Win/Cmd + + // USB#0700e8 - #07ffff are reserved + + // ================================== + // USB Usage Page 0x0c: Consumer Page + // ================================== + // AL = Application Launch + // AC = Application Control + + // TODO(garykac): Many XF86 keys have multiple scancodes mapping to them. + // We need to map all of these into a canonical USB scancode without + // confusing the reverse-lookup - most likely by simply returning the first + // found match. + + // TODO(garykac): Find appropriate mappings for: + // Win#e06b LaunchApp1 (My Computer?) + // Win#e021 LaunchApp2 (Calculator?) + // Win#e03c Music - USB#0c0193 is AL_AVCapturePlayback + // Win#e06d Video - USB#0c0193 is AL_AVCapturePlayback + // Win#e064 Pictures + // XKB#0080 XF86LaunchA + // XKB#0097 XF86WakeUp + // XKB#0099 XF86Send + // XKB#009b XF86Xfer + // XKB#009c XF86Launch1 + // XKB#009d XF86Launch2 + // XKB... remaining XF86 keys + + // USB XKB Win Mac + USB_KEYMAP(0x0c00b5, 0x0000, 0xe019, 0xffff, "MediaTrackNext"), + USB_KEYMAP(0x0c00b6, 0x0000, 0xe010, 0xffff, "MediaTrackPrevious"), + USB_KEYMAP(0x0c00b7, 0x0000, 0xe024, 0xffff, "MediaStop"), + USB_KEYMAP(0x0c00b8, 0x0000, 0xe02c, 0xffff, "Eject"), + USB_KEYMAP(0x0c00cd, 0x0000, 0xe022, 0xffff, "MediaPlayPause"), + USB_KEYMAP(0x0c018a, 0x0000, 0xe01e, 0xffff, "LaunchMail"), // AL_EmailReader + USB_KEYMAP(0x0c0192, 0x0094, 0x0000, 0xffff, NULL), // AL_Calculator + // USB#0c0194: My Computer + USB_KEYMAP(0x0c0194, 0x00a5, 0x0000, 0xffff, NULL), // AL_LocalMachineBrowser + USB_KEYMAP(0x0c01a7, 0x00f3, 0x0000, 0xffff, NULL), // AL_Documents + // USB#0c01b4: Home Directory + USB_KEYMAP(0x0c01b4, 0x0098, 0x0000, 0xffff, NULL), // AL_FileBrowser (Explorer) + USB_KEYMAP(0x0c0221, 0x0000, 0xe065, 0xffff, "BrowserSearch"), // AC_Search + USB_KEYMAP(0x0c0223, 0x0000, 0xe032, 0xffff, "BrowserHome"), // AC_Home + USB_KEYMAP(0x0c0224, 0x00a6, 0xe06a, 0xffff, "BrowserBack"), // AC_Back + USB_KEYMAP(0x0c0225, 0x00a7, 0xe069, 0xffff, "BrowserForward"), // AC_Forward + USB_KEYMAP(0x0c0226, 0x0000, 0xe068, 0xffff, "BrowserStop"), // AC_Stop + USB_KEYMAP(0x0c0227, 0x00b5, 0xe067, 0xffff, "BrowserRefresh"), // AC_Refresh (Reload) + USB_KEYMAP(0x0c022a, 0x00a4, 0xe066, 0xffff, NULL), // AC_Bookmarks (Favorites) + USB_KEYMAP(0x0c0289, 0x00f0, 0x0000, 0xffff, NULL), // AC_Reply + USB_KEYMAP(0x0c028b, 0x00f1, 0x0000, 0xffff, NULL), // AC_ForwardMsg (MailForward) + USB_KEYMAP(0x0c028c, 0x00ef, 0x0000, 0xffff, NULL), // AC_Send +}; + +#endif // UI_BASE_KEYCODES_KEYCODE_CONVERTER_DATA_H_ diff --git a/chromium/ui/base/keycodes/keycode_converter_unittest.cc b/chromium/ui/base/keycodes/keycode_converter_unittest.cc new file mode 100644 index 00000000000..3362d535684 --- /dev/null +++ b/chromium/ui/base/keycodes/keycode_converter_unittest.cc @@ -0,0 +1,110 @@ +// Copyright (c) 2012 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 "ui/base/keycodes/keycode_converter.h" + +#include <map> + +#include "base/basictypes.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ui::KeycodeConverter; + +namespace { + +#if defined(OS_WIN) +const size_t kExpectedMappedKeyCount = 138; +#elif defined(OS_LINUX) +const size_t kExpectedMappedKeyCount = 145; +#elif defined(OS_MACOSX) +const size_t kExpectedMappedKeyCount = 118; +#else +const size_t kExpectedMappedKeyCount = 0; +#endif + +const uint32_t kUsbNonExistentKeycode = 0xffffff; +const uint32_t kUsbUsBackslash = 0x070031; +const uint32_t kUsbNonUsHash = 0x070032; + +TEST(UsbKeycodeMap, Basic) { + ui::KeycodeConverter* key_converter = ui::KeycodeConverter::GetInstance(); + // Verify that the first element in the table is the "invalid" code. + const ui::KeycodeMapEntry* keycode_map = + key_converter->GetKeycodeMapForTest(); + EXPECT_EQ(key_converter->InvalidUsbKeycode(), keycode_map[0].usb_keycode); + EXPECT_EQ(key_converter->InvalidNativeKeycode(), + keycode_map[0].native_keycode); + EXPECT_STREQ(key_converter->InvalidKeyboardEventCode(), "Unidentified"); + EXPECT_EQ(key_converter->InvalidNativeKeycode(), + key_converter->CodeToNativeKeycode("Unidentified")); + + // Verify that there are no duplicate entries in the mapping. + std::map<uint32_t, uint16_t> usb_to_native; + std::map<uint16_t, uint32_t> native_to_usb; + size_t numEntries = key_converter->NumKeycodeMapEntriesForTest(); + for (size_t i = 0; i < numEntries; ++i) { + const ui::KeycodeMapEntry* entry = &keycode_map[i]; + // Don't test keys with no native keycode mapping on this platform. + if (entry->native_keycode == key_converter->InvalidNativeKeycode()) + continue; + + // Verify UsbKeycodeToNativeKeycode works for this key. + EXPECT_EQ(entry->native_keycode, + key_converter->UsbKeycodeToNativeKeycode(entry->usb_keycode)); + + // Verify CodeToNativeKeycode and NativeKeycodeToCode work correctly. + if (entry->code) { + EXPECT_EQ(entry->native_keycode, + key_converter->CodeToNativeKeycode(entry->code)); + EXPECT_STREQ(entry->code, + key_converter->NativeKeycodeToCode(entry->native_keycode)); + } + else { + EXPECT_EQ(key_converter->InvalidNativeKeycode(), + key_converter->CodeToNativeKeycode(entry->code)); + } + + // Verify that the USB or native codes aren't duplicated. + EXPECT_EQ(0U, usb_to_native.count(entry->usb_keycode)) + << " duplicate of USB code 0x" << std::hex << std::setfill('0') + << std::setw(6) << entry->usb_keycode + << " to native 0x" + << std::setw(4) << entry->native_keycode + << " (previous was 0x" + << std::setw(4) << usb_to_native[entry->usb_keycode] + << ")"; + usb_to_native[entry->usb_keycode] = entry->native_keycode; + EXPECT_EQ(0U, native_to_usb.count(entry->native_keycode)) + << " duplicate of native code 0x" << std::hex << std::setfill('0') + << std::setw(4) << entry->native_keycode + << " to USB 0x" + << std::setw(6) << entry->usb_keycode + << " (previous was 0x" + << std::setw(6) << native_to_usb[entry->native_keycode] + << ")"; + native_to_usb[entry->native_keycode] = entry->usb_keycode; + } + ASSERT_EQ(usb_to_native.size(), native_to_usb.size()); + + // Verify that the number of mapped keys is what we expect, i.e. we haven't + // lost any, and if we've added some then the expectation has been updated. + EXPECT_EQ(kExpectedMappedKeyCount, usb_to_native.size()); +} + +TEST(UsbKeycodeMap, NonExistent) { + // Verify that UsbKeycodeToNativeKeycode works for a non-existent USB keycode. + ui::KeycodeConverter* key_converter = ui::KeycodeConverter::GetInstance(); + EXPECT_EQ(key_converter->InvalidNativeKeycode(), + key_converter->UsbKeycodeToNativeKeycode(kUsbNonExistentKeycode)); +} + +TEST(UsbKeycodeMap, UsBackslashIsNonUsHash) { + // Verify that UsbKeycodeToNativeKeycode treats the non-US "hash" key + // as equivalent to the US "backslash" key. + ui::KeycodeConverter* key_converter = ui::KeycodeConverter::GetInstance(); + EXPECT_EQ(key_converter->UsbKeycodeToNativeKeycode(kUsbUsBackslash), + key_converter->UsbKeycodeToNativeKeycode(kUsbNonUsHash)); +} + +} // namespace diff --git a/chromium/ui/base/keycodes/usb_keycode_map.h b/chromium/ui/base/keycodes/usb_keycode_map.h deleted file mode 100644 index a5fca425589..00000000000 --- a/chromium/ui/base/keycodes/usb_keycode_map.h +++ /dev/null @@ -1,409 +0,0 @@ -// Copyright (c) 2012 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. - -// Data in this file was created by referencing: -// USB HID Usage Tables (v1.11) 27 June 2001 -// HIToolbox/Events.h (Mac) - -#include <stdint.h> - -typedef struct { - // USB keycode: - // Upper 16-bits: USB Usage Page. - // Lower 16-bits: USB Usage Id: Assigned ID within this usage page. - uint32_t usb_keycode; - - // Contains one of the following: - // On Linux: XKB scancode - // On Windows: Windows OEM scancode - // On Mac: Mac keycode - uint16_t native_keycode; -} usb_keymap; - -const usb_keymap usb_keycode_map[] = { - - // USB XKB Win Mac - USB_KEYMAP(0x000000, 0x0000, 0x0000, 0xffff), // Invalid - - // ========================================= - // USB Usage Page 0x01: Generic Desktop Page - // ========================================= - - // Sleep could be encoded as USB#0c0032, but there's no corresponding WakeUp - // in the 0x0c USB page. - - // USB XKB Win Mac - USB_KEYMAP(0x010082, 0x0096, 0x0000, 0xffff), // SystemSleep - USB_KEYMAP(0x010083, 0x0097, 0x0000, 0xffff), // SystemWakeUp - - // ========================================= - // USB Usage Page 0x07: Keyboard/Keypad Page - // ========================================= - - // TODO(garykac): - // XKB#005c ISO Level3 Shift - // XKB#005e <>|| - // XKB#006d Linefeed - // XKB#008a SunProps cf. USB#0700a3 CrSel/Props - // XKB#008e SunOpen - // Mac#003f kVK_Function - // Mac#000a kVK_ISO_Section (ISO keyboards only) - // Mac#0066 kVK_JIS_Eisu (USB#07008a Henkan?) - - // USB XKB Win Mac - USB_KEYMAP(0x070000, 0x0000, 0x0000, 0xffff), // Reserved - USB_KEYMAP(0x070001, 0x0000, 0x0000, 0xffff), // ErrorRollOver - USB_KEYMAP(0x070002, 0x0000, 0x0000, 0xffff), // POSTFail - USB_KEYMAP(0x070003, 0x0000, 0x0000, 0xffff), // ErrorUndefined - USB_KEYMAP(0x070004, 0x0026, 0x001e, 0x0000), // aA - USB_KEYMAP(0x070005, 0x0038, 0x0030, 0x000b), // bB - USB_KEYMAP(0x070006, 0x0036, 0x002e, 0x0008), // cC - USB_KEYMAP(0x070007, 0x0028, 0x0020, 0x0002), // dD - - USB_KEYMAP(0x070008, 0x001a, 0x0012, 0x000e), // eE - USB_KEYMAP(0x070009, 0x0029, 0x0021, 0x0003), // fF - USB_KEYMAP(0x07000a, 0x002a, 0x0022, 0x0005), // gG - USB_KEYMAP(0x07000b, 0x002b, 0x0023, 0x0004), // hH - USB_KEYMAP(0x07000c, 0x001f, 0x0017, 0x0022), // iI - USB_KEYMAP(0x07000d, 0x002c, 0x0024, 0x0026), // jJ - USB_KEYMAP(0x07000e, 0x002d, 0x0025, 0x0028), // kK - USB_KEYMAP(0x07000f, 0x002e, 0x0026, 0x0025), // lL - - USB_KEYMAP(0x070010, 0x003a, 0x0032, 0x002e), // mM - USB_KEYMAP(0x070011, 0x0039, 0x0031, 0x002d), // nN - USB_KEYMAP(0x070012, 0x0020, 0x0018, 0x001f), // oO - USB_KEYMAP(0x070013, 0x0021, 0x0019, 0x0023), // pP - USB_KEYMAP(0x070014, 0x0018, 0x0010, 0x000c), // qQ - USB_KEYMAP(0x070015, 0x001b, 0x0013, 0x000f), // rR - USB_KEYMAP(0x070016, 0x0027, 0x001f, 0x0001), // sS - USB_KEYMAP(0x070017, 0x001c, 0x0014, 0x0011), // tT - - USB_KEYMAP(0x070018, 0x001e, 0x0016, 0x0020), // uU - USB_KEYMAP(0x070019, 0x0037, 0x002f, 0x0009), // vV - USB_KEYMAP(0x07001a, 0x0019, 0x0011, 0x000d), // wW - USB_KEYMAP(0x07001b, 0x0035, 0x002d, 0x0007), // xX - USB_KEYMAP(0x07001c, 0x001d, 0x0015, 0x0010), // yY - USB_KEYMAP(0x07001d, 0x0034, 0x002c, 0x0006), // zZ - USB_KEYMAP(0x07001e, 0x000a, 0x0002, 0x0012), // 1! - USB_KEYMAP(0x07001f, 0x000b, 0x0003, 0x0013), // 2@ - - USB_KEYMAP(0x070020, 0x000c, 0x0004, 0x0014), // 3# - USB_KEYMAP(0x070021, 0x000d, 0x0005, 0x0015), // 4$ - USB_KEYMAP(0x070022, 0x000e, 0x0006, 0x0017), // 5% - USB_KEYMAP(0x070023, 0x000f, 0x0007, 0x0016), // 6^ - USB_KEYMAP(0x070024, 0x0010, 0x0008, 0x001a), // 7& - USB_KEYMAP(0x070025, 0x0011, 0x0009, 0x001c), // 8* - USB_KEYMAP(0x070026, 0x0012, 0x000a, 0x0019), // 9( - USB_KEYMAP(0x070027, 0x0013, 0x000b, 0x001d), // 0) - - USB_KEYMAP(0x070028, 0x0024, 0x001c, 0x0024), // Return - USB_KEYMAP(0x070029, 0x0009, 0x0001, 0x0035), // Escape - USB_KEYMAP(0x07002a, 0x0016, 0x000e, 0x0033), // Backspace - USB_KEYMAP(0x07002b, 0x0017, 0x000f, 0x0030), // Tab - USB_KEYMAP(0x07002c, 0x0041, 0x0039, 0x0031), // Spacebar - USB_KEYMAP(0x07002d, 0x0014, 0x000c, 0x001b), // -_ - USB_KEYMAP(0x07002e, 0x0015, 0x000d, 0x0018), // =+ - USB_KEYMAP(0x07002f, 0x0022, 0x001a, 0x0021), // [{ - - USB_KEYMAP(0x070030, 0x0023, 0x001b, 0x001e), // }] - USB_KEYMAP(0x070031, 0x0033, 0x002b, 0x002a), // \| (US keyboard only) - // USB#070032 never appears on keyboards that have USB#070031. - // Platforms use the same scancode as for the two keys. - // The keycap varies on international keyboards: - // Dan: '* Dutch: <> Ger: #' UK: #~ - // TODO(garykac): Verify Mac intl keyboard. - //USB_KEYMAP(0x070032, 0x0033, 0x002b, 0x002a), // #~ (Non-US) - USB_KEYMAP(0x070033, 0x002f, 0x0027, 0x0029), // ;: - USB_KEYMAP(0x070034, 0x0030, 0x0028, 0x0027), // '" - USB_KEYMAP(0x070035, 0x0031, 0x0029, 0x0032), // `~ - USB_KEYMAP(0x070036, 0x003b, 0x0033, 0x002b), // ,< - USB_KEYMAP(0x070037, 0x003c, 0x0034, 0x002f), // .> - - USB_KEYMAP(0x070038, 0x003d, 0x0035, 0x002c), // /? - // TODO(garykac): CapsLock requires special handling for each platform. - USB_KEYMAP(0x070039, 0x0042, 0x003a, 0x0039), // CapsLock - USB_KEYMAP(0x07003a, 0x0043, 0x003b, 0x007a), // F1 - USB_KEYMAP(0x07003b, 0x0044, 0x003c, 0x0078), // F2 - USB_KEYMAP(0x07003c, 0x0045, 0x003d, 0x0063), // F3 - USB_KEYMAP(0x07003d, 0x0046, 0x003e, 0x0076), // F4 - USB_KEYMAP(0x07003e, 0x0047, 0x003f, 0x0060), // F5 - USB_KEYMAP(0x07003f, 0x0048, 0x0040, 0x0061), // F6 - - USB_KEYMAP(0x070040, 0x0049, 0x0041, 0x0062), // F7 - USB_KEYMAP(0x070041, 0x004a, 0x0042, 0x0064), // F8 - USB_KEYMAP(0x070042, 0x004b, 0x0043, 0x0065), // F9 - USB_KEYMAP(0x070043, 0x004c, 0x0044, 0x006d), // F10 - USB_KEYMAP(0x070044, 0x005f, 0x0057, 0x0067), // F11 - USB_KEYMAP(0x070045, 0x0060, 0x0058, 0x006f), // F12 - // PrintScreen is effectively F13 on Mac OS X. - USB_KEYMAP(0x070046, 0x006b, 0xe037, 0xffff), // PrintScreen - USB_KEYMAP(0x070047, 0x004e, 0x0046, 0xffff), // ScrollLock - - USB_KEYMAP(0x070048, 0x007f, 0x0000, 0xffff), // Pause - // Labeled "Help/Insert" on Mac. - USB_KEYMAP(0x070049, 0x0076, 0xe052, 0x0072), // Insert - USB_KEYMAP(0x07004a, 0x006e, 0xe047, 0x0073), // Home - USB_KEYMAP(0x07004b, 0x0070, 0xe049, 0x0074), // PageUp - USB_KEYMAP(0x07004c, 0x0077, 0xe053, 0x0075), // Delete (Forward Delete) - USB_KEYMAP(0x07004d, 0x0073, 0xe04f, 0x0077), // End - USB_KEYMAP(0x07004e, 0x0075, 0xe051, 0x0079), // PageDown - USB_KEYMAP(0x07004f, 0x0072, 0xe04d, 0x007c), // RightArrow - - USB_KEYMAP(0x070050, 0x0071, 0xe04b, 0x007b), // LeftArrow - USB_KEYMAP(0x070051, 0x0074, 0xe050, 0x007d), // DownArrow - USB_KEYMAP(0x070052, 0x006f, 0xe048, 0x007e), // UpArrow - USB_KEYMAP(0x070053, 0x004d, 0x0045, 0x0047), // Keypad_NumLock Clear - USB_KEYMAP(0x070054, 0x006a, 0xe035, 0x004b), // Keypad_/ - USB_KEYMAP(0x070055, 0x003f, 0x0037, 0x0043), // Keypad_* - USB_KEYMAP(0x070056, 0x0052, 0x004a, 0x004e), // Keypad_- - USB_KEYMAP(0x070057, 0x0056, 0x004e, 0x0045), // Keypad_+ - - USB_KEYMAP(0x070058, 0x0068, 0xe01c, 0x004c), // Keypad_Enter - USB_KEYMAP(0x070059, 0x0057, 0x004f, 0x0053), // Keypad_1 End - USB_KEYMAP(0x07005a, 0x0058, 0x0050, 0x0054), // Keypad_2 DownArrow - USB_KEYMAP(0x07005b, 0x0059, 0x0051, 0x0055), // Keypad_3 PageDown - USB_KEYMAP(0x07005c, 0x0053, 0x004b, 0x0056), // Keypad_4 LeftArrow - USB_KEYMAP(0x07005d, 0x0054, 0x004c, 0x0057), // Keypad_5 - USB_KEYMAP(0x07005e, 0x0055, 0x004d, 0x0058), // Keypad_6 RightArrow - USB_KEYMAP(0x07005f, 0x004f, 0x0047, 0x0059), // Keypad_7 Home - - USB_KEYMAP(0x070060, 0x0050, 0x0048, 0x005b), // Keypad_8 UpArrow - USB_KEYMAP(0x070061, 0x0051, 0x0049, 0x005c), // Keypad_9 PageUp - USB_KEYMAP(0x070062, 0x005a, 0x0052, 0x0052), // Keypad_0 Insert - USB_KEYMAP(0x070063, 0x005b, 0x0053, 0x0041), // Keypad_. Delete - // USB#070064 is not present on US keyboard. - // This key is typically located near LeftShift key. - // The keycap varies on international keyboards: - // Dan: <> Dutch: ][ Ger: <> UK: \| - USB_KEYMAP(0x070064, 0x005e, 0x0056, 0x000a), // Non-US \| - USB_KEYMAP(0x070065, 0x0087, 0xe05d, 0x006e), // AppMenu (next to RWin key) - USB_KEYMAP(0x070066, 0x007c, 0x0000, 0xffff), // Power - USB_KEYMAP(0x070067, 0x007d, 0x0000, 0x0051), // Keypad_= - - USB_KEYMAP(0x070068, 0x0000, 0x005b, 0x0069), // F13 - USB_KEYMAP(0x070069, 0x0000, 0x005c, 0x006b), // F14 - USB_KEYMAP(0x07006a, 0x0000, 0x005d, 0x0071), // F15 - USB_KEYMAP(0x07006b, 0x0000, 0x0063, 0x006a), // F16 - USB_KEYMAP(0x07006c, 0x0000, 0x0064, 0x0040), // F17 - USB_KEYMAP(0x07006d, 0x0000, 0x0065, 0x004f), // F18 - USB_KEYMAP(0x07006e, 0x0000, 0x0066, 0x0050), // F19 - USB_KEYMAP(0x07006f, 0x0000, 0x0067, 0x005a), // F20 - - USB_KEYMAP(0x070070, 0x0000, 0x0068, 0xffff), // F21 - USB_KEYMAP(0x070071, 0x0000, 0x0069, 0xffff), // F22 - USB_KEYMAP(0x070072, 0x0000, 0x006a, 0xffff), // F23 - USB_KEYMAP(0x070073, 0x0000, 0x006b, 0xffff), // F24 - USB_KEYMAP(0x070074, 0x0000, 0x0000, 0xffff), // Execute - USB_KEYMAP(0x070075, 0x0092, 0xe03b, 0xffff), // Help - USB_KEYMAP(0x070076, 0x0093, 0x0000, 0xffff), // Menu - USB_KEYMAP(0x070077, 0x0000, 0x0000, 0xffff), // Select - - USB_KEYMAP(0x070078, 0x0000, 0x0000, 0xffff), // Stop - USB_KEYMAP(0x070079, 0x0089, 0x0000, 0xffff), // Again (Redo) - USB_KEYMAP(0x07007a, 0x008b, 0xe008, 0xffff), // Undo - USB_KEYMAP(0x07007b, 0x0091, 0xe017, 0xffff), // Cut - USB_KEYMAP(0x07007c, 0x008d, 0xe018, 0xffff), // Copy - USB_KEYMAP(0x07007d, 0x008f, 0xe00a, 0xffff), // Paste - USB_KEYMAP(0x07007e, 0x0090, 0x0000, 0xffff), // Find - USB_KEYMAP(0x07007f, 0x0079, 0xe020, 0x004a), // Mute - - USB_KEYMAP(0x070080, 0x007b, 0xe030, 0x0048), // VolumeUp - USB_KEYMAP(0x070081, 0x007a, 0xe02e, 0x0049), // VolumeDown - USB_KEYMAP(0x070082, 0x0000, 0x0000, 0xffff), // LockingCapsLock - USB_KEYMAP(0x070083, 0x0000, 0x0000, 0xffff), // LockingNumLock - USB_KEYMAP(0x070084, 0x0000, 0x0000, 0xffff), // LockingScrollLock - // USB#070085 is used as Brazilian Keypad_. - USB_KEYMAP(0x070085, 0x0000, 0x0000, 0x005f), // Keypad_Comma - // USB#070086 is used on AS/400 keyboards. Standard Keypad_= is USB#070067. - //USB_KEYMAP(0x070086, 0x0000, 0x0000, 0xffff), // Keypad_= - // USB#070087 is used for Brazilian /? and Japanese _ 'ro'. - USB_KEYMAP(0x070087, 0x0061, 0x0000, 0x005e), // International1 - - // USB#070088 is used as Japanese Hiragana/Katakana key. - USB_KEYMAP(0x070088, 0x0065, 0x0000, 0x0068), // International2 - // USB#070089 is used as Japanese Yen key. - USB_KEYMAP(0x070089, 0x0084, 0x007d, 0x005d), // International3 - // USB#07008a is used as Japanese Henkan (Convert) key. - USB_KEYMAP(0x07008a, 0x0064, 0x0000, 0xffff), // International4 - // USB#07008b is used as Japanese Muhenkan (No-convert) key. - USB_KEYMAP(0x07008b, 0x0066, 0x0000, 0xffff), // International5 - USB_KEYMAP(0x07008c, 0x0000, 0x0000, 0xffff), // International6 - USB_KEYMAP(0x07008d, 0x0000, 0x0000, 0xffff), // International7 - USB_KEYMAP(0x07008e, 0x0000, 0x0000, 0xffff), // International8 - USB_KEYMAP(0x07008f, 0x0000, 0x0000, 0xffff), // International9 - - // USB#070090 is used as Korean Hangul/English toggle key. - USB_KEYMAP(0x070090, 0x0082, 0x0000, 0xffff), // LANG1 - // USB#070091 is used as Korean Hanja conversion key. - USB_KEYMAP(0x070091, 0x0083, 0x0000, 0xffff), // LANG2 - // USB#070092 is used as Japanese Katakana key. - USB_KEYMAP(0x070092, 0x0062, 0x0000, 0xffff), // LANG3 - // USB#070093 is used as Japanese Hiragana key. - USB_KEYMAP(0x070093, 0x0063, 0x0000, 0xffff), // LANG4 - // USB#070094 is used as Japanese Zenkaku/Hankaku (Fullwidth/halfwidth) key. - USB_KEYMAP(0x070094, 0x0000, 0x0000, 0xffff), // LANG5 - USB_KEYMAP(0x070095, 0x0000, 0x0000, 0xffff), // LANG6 - USB_KEYMAP(0x070096, 0x0000, 0x0000, 0xffff), // LANG7 - USB_KEYMAP(0x070097, 0x0000, 0x0000, 0xffff), // LANG8 - - USB_KEYMAP(0x070098, 0x0000, 0x0000, 0xffff), // LANG9 - USB_KEYMAP(0x070099, 0x0000, 0x0000, 0xffff), // AlternateErase - USB_KEYMAP(0x07009a, 0x0000, 0x0000, 0xffff), // SysReq/Attention - USB_KEYMAP(0x07009b, 0x0088, 0x0000, 0xffff), // Cancel - USB_KEYMAP(0x07009c, 0x0000, 0x0000, 0xffff), // Clear - USB_KEYMAP(0x07009d, 0x0000, 0x0000, 0xffff), // Prior - USB_KEYMAP(0x07009e, 0x0000, 0x0000, 0xffff), // Return - USB_KEYMAP(0x07009f, 0x0000, 0x0000, 0xffff), // Separator - - USB_KEYMAP(0x0700a0, 0x0000, 0x0000, 0xffff), // Out - USB_KEYMAP(0x0700a1, 0x0000, 0x0000, 0xffff), // Oper - USB_KEYMAP(0x0700a2, 0x0000, 0x0000, 0xffff), // Clear/Again - USB_KEYMAP(0x0700a3, 0x0000, 0x0000, 0xffff), // CrSel/Props - USB_KEYMAP(0x0700a4, 0x0000, 0x0000, 0xffff), // ExSel - - //USB_KEYMAP(0x0700b0, 0x0000, 0x0000, 0xffff), // Keypad_00 - //USB_KEYMAP(0x0700b1, 0x0000, 0x0000, 0xffff), // Keypad_000 - //USB_KEYMAP(0x0700b2, 0x0000, 0x0000, 0xffff), // ThousandsSeparator - //USB_KEYMAP(0x0700b3, 0x0000, 0x0000, 0xffff), // DecimalSeparator - //USB_KEYMAP(0x0700b4, 0x0000, 0x0000, 0xffff), // CurrencyUnit - //USB_KEYMAP(0x0700b5, 0x0000, 0x0000, 0xffff), // CurrencySubunit - USB_KEYMAP(0x0700b6, 0x00bb, 0x0000, 0xffff), // Keypad_( - USB_KEYMAP(0x0700b7, 0x00bc, 0x0000, 0xffff), // Keypad_) - - //USB_KEYMAP(0x0700b8, 0x0000, 0x0000, 0xffff), // Keypad_{ - //USB_KEYMAP(0x0700b9, 0x0000, 0x0000, 0xffff), // Keypad_} - //USB_KEYMAP(0x0700ba, 0x0000, 0x0000, 0xffff), // Keypad_Tab - //USB_KEYMAP(0x0700bb, 0x0000, 0x0000, 0xffff), // Keypad_Backspace - //USB_KEYMAP(0x0700bc, 0x0000, 0x0000, 0xffff), // Keypad_A - //USB_KEYMAP(0x0700bd, 0x0000, 0x0000, 0xffff), // Keypad_B - //USB_KEYMAP(0x0700be, 0x0000, 0x0000, 0xffff), // Keypad_C - //USB_KEYMAP(0x0700bf, 0x0000, 0x0000, 0xffff), // Keypad_D - - //USB_KEYMAP(0x0700c0, 0x0000, 0x0000, 0xffff), // Keypad_E - //USB_KEYMAP(0x0700c1, 0x0000, 0x0000, 0xffff), // Keypad_F - //USB_KEYMAP(0x0700c2, 0x0000, 0x0000, 0xffff), // Keypad_Xor - //USB_KEYMAP(0x0700c3, 0x0000, 0x0000, 0xffff), // Keypad_^ - //USB_KEYMAP(0x0700c4, 0x0000, 0x0000, 0xffff), // Keypad_% - //USB_KEYMAP(0x0700c5, 0x0000, 0x0000, 0xffff), // Keypad_< - //USB_KEYMAP(0x0700c6, 0x0000, 0x0000, 0xffff), // Keypad_> - //USB_KEYMAP(0x0700c7, 0x0000, 0x0000, 0xffff), // Keypad_& - - //USB_KEYMAP(0x0700c8, 0x0000, 0x0000, 0xffff), // Keypad_&& - //USB_KEYMAP(0x0700c9, 0x0000, 0x0000, 0xffff), // Keypad_| - //USB_KEYMAP(0x0700ca, 0x0000, 0x0000, 0xffff), // Keypad_|| - //USB_KEYMAP(0x0700cb, 0x0000, 0x0000, 0xffff), // Keypad_: - //USB_KEYMAP(0x0700cc, 0x0000, 0x0000, 0xffff), // Keypad_# - //USB_KEYMAP(0x0700cd, 0x0000, 0x0000, 0xffff), // Keypad_Space - //USB_KEYMAP(0x0700ce, 0x0000, 0x0000, 0xffff), // Keypad_@ - //USB_KEYMAP(0x0700cf, 0x0000, 0x0000, 0xffff), // Keypad_! - - //USB_KEYMAP(0x0700d0, 0x0000, 0x0000, 0xffff), // Keypad_MemoryStore - //USB_KEYMAP(0x0700d1, 0x0000, 0x0000, 0xffff), // Keypad_MemoryRecall - //USB_KEYMAP(0x0700d2, 0x0000, 0x0000, 0xffff), // Keypad_MemoryClear - //USB_KEYMAP(0x0700d3, 0x0000, 0x0000, 0xffff), // Keypad_MemoryAdd - //USB_KEYMAP(0x0700d4, 0x0000, 0x0000, 0xffff), // Keypad_MemorySubtract - //USB_KEYMAP(0x0700d5, 0x0000, 0x0000, 0xffff), // Keypad_MemoryMultiply - //USB_KEYMAP(0x0700d6, 0x0000, 0x0000, 0xffff), // Keypad_MemoryDivide - USB_KEYMAP(0x0700d7, 0x007e, 0x0000, 0xffff), // Keypad_+/- - - //USB_KEYMAP(0x0700d8, 0x0000, 0x0000, 0xffff), // Keypad_Clear - //USB_KEYMAP(0x0700d9, 0x0000, 0x0000, 0xffff), // Keypad_ClearEntry - //USB_KEYMAP(0x0700da, 0x0000, 0x0000, 0xffff), // Keypad_Binary - //USB_KEYMAP(0x0700db, 0x0000, 0x0000, 0xffff), // Keypad_Octal - USB_KEYMAP(0x0700dc, 0x0081, 0x0000, 0xffff), // Keypad_Decimal - //USB_KEYMAP(0x0700dd, 0x0000, 0x0000, 0xffff), // Keypad_Hexadecimal - // USB#0700de - #0700df are reserved. - - USB_KEYMAP(0x0700e0, 0x0025, 0x001d, 0x003b), // LeftControl - USB_KEYMAP(0x0700e1, 0x0032, 0x002a, 0x0038), // LeftShift - USB_KEYMAP(0x0700e2, 0x0040, 0x0038, 0x003a), // LeftAlt/Option - USB_KEYMAP(0x0700e3, 0x0085, 0xe05b, 0x0037), // LeftGUI/Super/Win/Cmd - USB_KEYMAP(0x0700e4, 0x0069, 0xe01d, 0x003e), // RightControl - USB_KEYMAP(0x0700e5, 0x003e, 0x0036, 0x003c), // RightShift - USB_KEYMAP(0x0700e6, 0x006c, 0xe038, 0x003d), // RightAlt/Option - USB_KEYMAP(0x0700e7, 0x0086, 0xe05c, 0x0036), // RightGUI/Super/Win/Cmd - - // USB#0700e8 - #07ffff are reserved - - // ================================== - // USB Usage Page 0x0c: Consumer Page - // ================================== - // AL = Application Launch - // AC = Application Control - - // TODO(garykac): Many XF86 keys have multiple scancodes mapping to them. - // We need to map all of these into a canonical USB scancode without - // confusing the reverse-lookup - most likely by simply returning the first - // found match. - - // TODO(garykac): Find appropriate mappings for: - // Win#e06b LaunchApp1 (My Computer?) - // Win#e021 LaunchApp2 (Calculator?) - // Win#e03c Music - USB#0c0193 is AL_AVCapturePlayback - // Win#e06d Video - USB#0c0193 is AL_AVCapturePlayback - // Win#e064 Pictures - // XKB#0080 XF86LaunchA - // XKB#0097 XF86WakeUp - // XKB#0099 XF86Send - // XKB#009b XF86Xfer - // XKB#009c XF86Launch1 - // XKB#009d XF86Launch2 - // XKB... remaining XF86 keys - - // USB XKB Win Mac - USB_KEYMAP(0x0c00b5, 0x0000, 0xe019, 0xffff), // ScanNextTrack - USB_KEYMAP(0x0c00b6, 0x0000, 0xe010, 0xffff), // ScanPreviousTrack - USB_KEYMAP(0x0c00b7, 0x0000, 0xe024, 0xffff), // Stop - USB_KEYMAP(0x0c00b8, 0x0000, 0xe02c, 0xffff), // Eject - USB_KEYMAP(0x0c00cd, 0x0000, 0xe022, 0xffff), // Play/Pause - USB_KEYMAP(0x0c018a, 0x0000, 0xe01e, 0xffff), // AL_EmailReader - USB_KEYMAP(0x0c0192, 0x0094, 0x0000, 0xffff), // AL_Calculator - // USB#0c0194: My Computer - USB_KEYMAP(0x0c0194, 0x00a5, 0x0000, 0xffff), // AL_LocalMachineBrowser - USB_KEYMAP(0x0c01a7, 0x00f3, 0x0000, 0xffff), // AL_Documents - // USB#0c01b4: Home Directory - USB_KEYMAP(0x0c01b4, 0x0098, 0x0000, 0xffff), // AL_FileBrowser (Explorer) - USB_KEYMAP(0x0c0221, 0x0000, 0xe065, 0xffff), // AC_Search - USB_KEYMAP(0x0c0223, 0x0000, 0xe032, 0xffff), // AC_Home - USB_KEYMAP(0x0c0224, 0x00a6, 0xe06a, 0xffff), // AC_Back - USB_KEYMAP(0x0c0225, 0x00a7, 0xe069, 0xffff), // AC_Forward - USB_KEYMAP(0x0c0226, 0x0000, 0xe068, 0xffff), // AC_Stop - USB_KEYMAP(0x0c0227, 0x00b5, 0xe067, 0xffff), // AC_Refresh (Reload) - USB_KEYMAP(0x0c022a, 0x00a4, 0xe066, 0xffff), // AC_Bookmarks (Favorites) - USB_KEYMAP(0x0c0289, 0x00f0, 0x0000, 0xffff), // AC_Reply - USB_KEYMAP(0x0c028b, 0x00f1, 0x0000, 0xffff), // AC_ForwardMsg (MailForward) - USB_KEYMAP(0x0c028c, 0x00ef, 0x0000, 0xffff), // AC_Send -}; - -inline uint16_t InvalidNativeKeycode() { - return usb_keycode_map[0].native_keycode; -} - -inline uint16_t InvalidUsbKeycode() { - return usb_keycode_map[0].usb_keycode; -} - -inline uint16_t UsbKeycodeToNativeKeycode(uint32_t usb_keycode) { - // Deal with some special-cases that don't fit the 1:1 mapping. - if (usb_keycode == 0x070032) // non-US hash. - usb_keycode = 0x070031; // US backslash. -#if defined(OS_MACOSX) - if (usb_keycode == 0x070046) // PrintScreen. - usb_keycode = 0x070068; // F13. -#endif - - for (size_t i = 0; i < arraysize(usb_keycode_map); ++i) { - if (usb_keycode_map[i].usb_keycode == usb_keycode) - return usb_keycode_map[i].native_keycode; - } - return InvalidNativeKeycode(); -} - -inline uint32_t NativeKeycodeToUsbKeycode(uint16_t native_keycode) { - for (size_t i = 0; i < arraysize(usb_keycode_map); ++i) { - if (usb_keycode_map[i].native_keycode == native_keycode) - return usb_keycode_map[i].usb_keycode; - } - return InvalidUsbKeycode(); -} diff --git a/chromium/ui/base/keycodes/usb_keycode_map_unittest.cc b/chromium/ui/base/keycodes/usb_keycode_map_unittest.cc deleted file mode 100644 index 46093bc50f1..00000000000 --- a/chromium/ui/base/keycodes/usb_keycode_map_unittest.cc +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2012 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 <map> - -#include "base/basictypes.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -#if defined(OS_WIN) -const size_t kExpectedMappedKeyCount = 138; -#define USB_KEYMAP(usb, xkb, win, mac) {usb, win} -#elif defined(OS_LINUX) -const size_t kExpectedMappedKeyCount = 145; -#define USB_KEYMAP(usb, xkb, win, mac) {usb, xkb} -#elif defined(OS_MACOSX) -const size_t kExpectedMappedKeyCount = 118; -#define USB_KEYMAP(usb, xkb, win, mac) {usb, mac} -#else -const size_t kExpectedMappedKeyCount = 0; -#define USB_KEYMAP(usb, xkb, win, mac) {usb, 0} -#endif -#include "ui/base/keycodes/usb_keycode_map.h" -#undef USB_KEYMAP - -const uint32_t kUsbNonExistentKeycode = 0xffffff; -const uint32_t kUsbUsBackslash = 0x070031; -const uint32_t kUsbNonUsHash = 0x070032; - -TEST(UsbKeycodeMap, Basic) { - // Verify that the first element in the table is the "invalid" code. - EXPECT_EQ(InvalidUsbKeycode(), usb_keycode_map[0].usb_keycode); - EXPECT_EQ(InvalidNativeKeycode(), usb_keycode_map[0].native_keycode); - - // Verify that there are no duplicate entries in the mapping. - std::map<uint32_t, uint16_t> usb_to_native; - std::map<uint16_t, uint32_t> native_to_usb; - for (size_t i = 0; i < arraysize(usb_keycode_map); ++i) { - // Don't test keys with no native keycode mapping on this platform. - if (usb_keycode_map[i].native_keycode == InvalidNativeKeycode()) - continue; - - // Verify UsbKeycodeToNativeKeycode works for this key. - EXPECT_EQ(usb_keycode_map[i].native_keycode, - UsbKeycodeToNativeKeycode(usb_keycode_map[i].usb_keycode)); - - // Verify that the USB or native codes aren't duplicated. - EXPECT_EQ(0U, usb_to_native.count(usb_keycode_map[i].usb_keycode)) - << " duplicate of USB code 0x" << std::hex << std::setfill('0') - << std::setw(6) << usb_keycode_map[i].usb_keycode - << " to native 0x" - << std::setw(4) << usb_keycode_map[i].native_keycode - << " (previous was 0x" - << std::setw(4) << usb_to_native[usb_keycode_map[i].usb_keycode] - << ")"; - usb_to_native[usb_keycode_map[i].usb_keycode] = - usb_keycode_map[i].native_keycode; - EXPECT_EQ(0U, native_to_usb.count(usb_keycode_map[i].native_keycode)) - << " duplicate of native code 0x" << std::hex << std::setfill('0') - << std::setw(4) << usb_keycode_map[i].native_keycode - << " to USB 0x" - << std::setw(6) << usb_keycode_map[i].usb_keycode - << " (previous was 0x" - << std::setw(6) << native_to_usb[usb_keycode_map[i].native_keycode] - << ")"; - native_to_usb[usb_keycode_map[i].native_keycode] = - usb_keycode_map[i].usb_keycode; - } - ASSERT_EQ(usb_to_native.size(), native_to_usb.size()); - - // Verify that the number of mapped keys is what we expect, i.e. we haven't - // lost any, and if we've added some then the expectation has been updated. - EXPECT_EQ(kExpectedMappedKeyCount, usb_to_native.size()); -} - -TEST(UsbKeycodeMap, NonExistent) { - // Verify that UsbKeycodeToNativeKeycode works for a non-existent USB keycode. - EXPECT_EQ(InvalidNativeKeycode(), - UsbKeycodeToNativeKeycode(kUsbNonExistentKeycode)); -} - -TEST(UsbKeycodeMap, UsBackslashIsNonUsHash) { - // Verify that UsbKeycodeToNativeKeycode treats the non-US "hash" key - // as equivalent to the US "backslash" key. - EXPECT_EQ(UsbKeycodeToNativeKeycode(kUsbUsBackslash), - UsbKeycodeToNativeKeycode(kUsbNonUsHash)); - -} - -} // namespace diff --git a/chromium/ui/base/l10n/l10n_util.cc b/chromium/ui/base/l10n/l10n_util.cc index 513a615a141..96dfa8e868b 100644 --- a/chromium/ui/base/l10n/l10n_util.cc +++ b/chromium/ui/base/l10n/l10n_util.cc @@ -28,6 +28,7 @@ #include "third_party/icu/source/common/unicode/rbbi.h" #include "third_party/icu/source/common/unicode/uloc.h" #include "ui/base/l10n/l10n_util_collator.h" +#include "ui/base/l10n/l10n_util_plurals.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_base_paths.h" @@ -35,7 +36,7 @@ #include "ui/base/l10n/l10n_util_android.h" #endif -#if defined(OS_LINUX) +#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) #include <glib.h> #endif @@ -452,7 +453,7 @@ std::string GetApplicationLocale(const std::string& pref_locale) { // On Android, query java.util.Locale for the default locale. candidates.push_back(GetDefaultLocale()); -#elif defined(OS_LINUX) +#elif defined(OS_POSIX) // If we're on a different Linux system, we have glib. // GLib implements correct environment variable parsing with @@ -831,6 +832,27 @@ bool StringComparator<string16>::operator()(const string16& lhs, UCOL_LESS; }; +string16 GetPluralStringFUTF16(const std::vector<int>& message_ids, + int number) { + scoped_ptr<icu::PluralFormat> format = BuildPluralFormat(message_ids); + DCHECK(format); + + UErrorCode err = U_ZERO_ERROR; + icu::UnicodeString result_files_string = format->format(number, err); + int capacity = result_files_string.length() + 1; + DCHECK_GT(capacity, 1); + string16 result; + result_files_string.extract( + static_cast<UChar*>(WriteInto(&result, capacity)), capacity, err); + DCHECK(U_SUCCESS(err)); + return result; +} + +std::string GetPluralStringFUTF8(const std::vector<int>& message_ids, + int number) { + return base::UTF16ToUTF8(GetPluralStringFUTF16(message_ids, number)); +} + void SortStrings16(const std::string& locale, std::vector<string16>* strings) { SortVectorWithStringKey(locale, strings, false); diff --git a/chromium/ui/base/l10n/l10n_util.h b/chromium/ui/base/l10n/l10n_util.h index 7c26b803467..d7753365d00 100644 --- a/chromium/ui/base/l10n/l10n_util.h +++ b/chromium/ui/base/l10n/l10n_util.h @@ -139,6 +139,14 @@ UI_EXPORT string16 GetStringFUTF16(int message_id, UI_EXPORT string16 GetStringFUTF16Int(int message_id, int a); string16 GetStringFUTF16Int(int message_id, int64 a); +// Get a resource string using |number| to decide which of |message_ids| should +// be used. |message_ids| must be size 6 and in order: default, singular, zero, +// two, few, many. +UI_EXPORT string16 GetPluralStringFUTF16(const std::vector<int>& message_ids, + int number); +UI_EXPORT std::string GetPluralStringFUTF8(const std::vector<int>& message_ids, + int number); + // In place sorting of string16 strings using collation rules for |locale|. UI_EXPORT void SortStrings16(const std::string& locale, std::vector<string16>* strings); diff --git a/chromium/ui/base/l10n/l10n_util_plurals.cc b/chromium/ui/base/l10n/l10n_util_plurals.cc new file mode 100644 index 00000000000..0dc008ff06e --- /dev/null +++ b/chromium/ui/base/l10n/l10n_util_plurals.cc @@ -0,0 +1,64 @@ +// 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 "ui/base/l10n/l10n_util_plurals.h" + +#include "base/memory/scoped_ptr.h" +#include "ui/base/l10n/l10n_util.h" + +namespace l10n_util { + +scoped_ptr<icu::PluralRules> BuildPluralRules() { + UErrorCode err = U_ZERO_ERROR; + scoped_ptr<icu::PluralRules> rules( + icu::PluralRules::forLocale(icu::Locale::getDefault(), err)); + if (U_FAILURE(err)) { + err = U_ZERO_ERROR; + icu::UnicodeString fallback_rules("one: n is 1", -1, US_INV); + rules.reset(icu::PluralRules::createRules(fallback_rules, err)); + DCHECK(U_SUCCESS(err)); + } + return rules.Pass(); +} + +scoped_ptr<icu::PluralFormat> BuildPluralFormat( + const std::vector<int>& message_ids) { + const icu::UnicodeString kKeywords[] = { + UNICODE_STRING_SIMPLE("other"), + UNICODE_STRING_SIMPLE("one"), + UNICODE_STRING_SIMPLE("zero"), + UNICODE_STRING_SIMPLE("two"), + UNICODE_STRING_SIMPLE("few"), + UNICODE_STRING_SIMPLE("many"), + }; + DCHECK_EQ(message_ids.size(), arraysize(kKeywords)); + UErrorCode err = U_ZERO_ERROR; + scoped_ptr<icu::PluralRules> rules(BuildPluralRules()); + + icu::UnicodeString pattern; + for (size_t i = 0; i < arraysize(kKeywords); ++i) { + int msg_id = message_ids[i]; + std::string sub_pattern = GetStringUTF8(msg_id); + // NA means this keyword is not used in the current locale. + // Even if a translator translated for this keyword, we do not + // use it unless it's 'other' (i=0) or it's defined in the rules + // for the current locale. Special-casing of 'other' will be removed + // once ICU's isKeyword is fixed to return true for isKeyword('other'). + if (sub_pattern.compare("NA") != 0 && + (i == 0 || rules->isKeyword(kKeywords[i]))) { + pattern += kKeywords[i]; + pattern += UNICODE_STRING_SIMPLE("{"); + pattern += icu::UnicodeString(sub_pattern.c_str(), "UTF-8"); + pattern += UNICODE_STRING_SIMPLE("}"); + } + } + scoped_ptr<icu::PluralFormat> format = scoped_ptr<icu::PluralFormat>( + new icu::PluralFormat(*rules, pattern, err)); + if (!U_SUCCESS(err)) { + return scoped_ptr<icu::PluralFormat>(); + } + return format.Pass(); +} + +} // namespace l10n_util diff --git a/chromium/ui/base/l10n/l10n_util_plurals.h b/chromium/ui/base/l10n/l10n_util_plurals.h new file mode 100644 index 00000000000..203797d6c44 --- /dev/null +++ b/chromium/ui/base/l10n/l10n_util_plurals.h @@ -0,0 +1,30 @@ +// 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. + +// This file contains utility functions for dealing with pluralization of +// localized content. + +#ifndef UI_BASE_L10N_L10N_UTIL_PLURALS_H_ +#define UI_BASE_L10N_L10N_UTIL_PLURALS_H_ + +#include <string> +#include <vector> + +#include "base/memory/scoped_ptr.h" +#include "third_party/icu/source/i18n/unicode/plurfmt.h" +#include "third_party/icu/source/i18n/unicode/plurrule.h" + +namespace l10n_util { + +// Returns a PluralRules for the current locale. +scoped_ptr<icu::PluralRules> BuildPluralRules(); + +// Returns a PluralFormat from |message_ids|. |message_ids| must be size 6 and +// in order: default, singular, zero, two, few, many. +scoped_ptr<icu::PluralFormat> BuildPluralFormat( + const std::vector<int>& message_ids); + +} // namespace l10n_util + +#endif // UI_BASE_L10N_L10N_UTIL_PLURALS_H_ diff --git a/chromium/ui/base/l10n/l10n_util_win.cc b/chromium/ui/base/l10n/l10n_util_win.cc index 123b74f6abf..0fa34cfbfaf 100644 --- a/chromium/ui/base/l10n/l10n_util_win.cc +++ b/chromium/ui/base/l10n/l10n_util_win.cc @@ -15,7 +15,7 @@ #include "base/win/windows_version.h" #include "grit/app_locale_settings.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/win/dpi.h" +#include "ui/gfx/win/dpi.h" namespace { @@ -151,7 +151,7 @@ bool NeedOverrideDefaultUIFont(string16* override_font_family, } void AdjustUIFont(LOGFONT* logfont) { - AdjustUIFontForDIP(ui::GetDPIScale(), logfont); + AdjustUIFontForDIP(gfx::GetDPIScale(), logfont); } void AdjustUIFontForDIP(float dpi_scale, LOGFONT* logfont) { diff --git a/chromium/ui/base/l10n/l10n_util_win_unittest.cc b/chromium/ui/base/l10n/l10n_util_win_unittest.cc index 10e496338bc..c4ae8885b7e 100644 --- a/chromium/ui/base/l10n/l10n_util_win_unittest.cc +++ b/chromium/ui/base/l10n/l10n_util_win_unittest.cc @@ -9,7 +9,7 @@ #include "base/win/win_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" -#include "ui/base/win/dpi.h" +#include "ui/gfx/win/dpi.h" typedef PlatformTest L10nUtilWinTest; diff --git a/chromium/ui/base/l10n/time_format.cc b/chromium/ui/base/l10n/time_format.cc index 5ba606c3dfb..aaa35a99699 100644 --- a/chromium/ui/base/l10n/time_format.cc +++ b/chromium/ui/base/l10n/time_format.cc @@ -21,6 +21,7 @@ #include "third_party/icu/source/i18n/unicode/plurrule.h" #include "third_party/icu/source/i18n/unicode/smpdtfmt.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/base/l10n/l10n_util_plurals.h" using base::Time; using base::TimeDelta; @@ -240,49 +241,20 @@ static base::LazyInstance<TimeFormatter> g_time_formatter = void TimeFormatter::BuildFormats( FormatType format_type, ScopedVector<icu::PluralFormat>* time_formats) { - const icu::UnicodeString kKeywords[] = { - UNICODE_STRING_SIMPLE("other"), UNICODE_STRING_SIMPLE("one"), - UNICODE_STRING_SIMPLE("zero"), UNICODE_STRING_SIMPLE("two"), - UNICODE_STRING_SIMPLE("few"), UNICODE_STRING_SIMPLE("many") - }; - UErrorCode err = U_ZERO_ERROR; - scoped_ptr<icu::PluralRules> rules( - icu::PluralRules::forLocale(icu::Locale::getDefault(), err)); - if (U_FAILURE(err)) { - err = U_ZERO_ERROR; - icu::UnicodeString fallback_rules("one: n is 1", -1, US_INV); - rules.reset(icu::PluralRules::createRules(fallback_rules, err)); - DCHECK(U_SUCCESS(err)); - } - const MessageIDs& message_ids = GetMessageIDs(format_type); for (int i = 0; i < 4; ++i) { icu::UnicodeString pattern; - for (size_t j = 0; j < arraysize(kKeywords); ++j) { - int msg_id = message_ids.ids[i][j]; - std::string sub_pattern = l10n_util::GetStringUTF8(msg_id); - // NA means this keyword is not used in the current locale. - // Even if a translator translated for this keyword, we do not - // use it unless it's 'other' (j=0) or it's defined in the rules - // for the current locale. Special-casing of 'other' will be removed - // once ICU's isKeyword is fixed to return true for isKeyword('other'). - if (sub_pattern.compare("NA") != 0 && - (j == 0 || rules->isKeyword(kKeywords[j]))) { - pattern += kKeywords[j]; - pattern += UNICODE_STRING_SIMPLE("{"); - pattern += icu::UnicodeString(sub_pattern.c_str(), "UTF-8"); - pattern += UNICODE_STRING_SIMPLE("}"); - } + std::vector<int> ids; + for (size_t j = 0; j < arraysize(message_ids.ids[i]); ++j) { + ids.push_back(message_ids.ids[i][j]); } - icu::PluralFormat* format = new icu::PluralFormat(*rules, pattern, err); - if (U_SUCCESS(err)) { - time_formats->push_back(format); + scoped_ptr<icu::PluralFormat> format = l10n_util::BuildPluralFormat(ids); + if (format) { + time_formats->push_back(format.release()); } else { - delete format; + scoped_ptr<icu::PluralRules> rules(l10n_util::BuildPluralRules()); time_formats->push_back(createFallbackFormat(*rules, i, format_type)); - // Reset it so that next ICU call can proceed. - err = U_ZERO_ERROR; } } } diff --git a/chromium/ui/base/layout.cc b/chromium/ui/base/layout.cc index 024948cd5ee..40a0a9ccc32 100644 --- a/chromium/ui/base/layout.cc +++ b/chromium/ui/base/layout.cc @@ -23,7 +23,7 @@ #if defined(OS_WIN) #include "base/win/metro.h" -#include "ui/base/win/dpi.h" +#include "ui/gfx/win/dpi.h" #include <Windows.h> #endif // defined(OS_WIN) @@ -66,7 +66,8 @@ bool UseTouchOptimizedUI() { } #endif // defined(OS_WIN) -const float kScaleFactorScales[] = {1.0f, 1.0f, 1.33f, 1.4f, 1.5f, 1.8f, 2.0f}; +const float kScaleFactorScales[] = {1.0f, 1.0f, 1.25f, 1.33f, 1.4f, 1.5f, 1.8f, + 2.0f}; COMPILE_ASSERT(NUM_SCALE_FACTORS == arraysize(kScaleFactorScales), kScaleFactorScales_incorrect_size); const size_t kScaleFactorScalesLength = arraysize(kScaleFactorScales); @@ -123,7 +124,7 @@ std::vector<ScaleFactor>& GetSupportedScaleFactorsInternal() { // Have high-DPI resources for 140% and 180% scaling on Windows based on // default scaling for Metro mode. Round to nearest supported scale in // all cases. - if (ui::IsInHighDPIMode()) { + if (gfx::IsInHighDPIMode()) { supported_scale_factors->push_back(SCALE_FACTOR_140P); supported_scale_factors->push_back(SCALE_FACTOR_180P); } diff --git a/chromium/ui/base/layout.h b/chromium/ui/base/layout.h index 236e58ece61..1292c38f2c5 100644 --- a/chromium/ui/base/layout.h +++ b/chromium/ui/base/layout.h @@ -36,6 +36,7 @@ UI_EXPORT DisplayLayout GetDisplayLayout(); enum ScaleFactor { SCALE_FACTOR_NONE = 0, SCALE_FACTOR_100P, + SCALE_FACTOR_125P, SCALE_FACTOR_133P, SCALE_FACTOR_140P, SCALE_FACTOR_150P, diff --git a/chromium/ui/base/layout_unittest.cc b/chromium/ui/base/layout_unittest.cc index a230d5ae666..8a741821e8c 100644 --- a/chromium/ui/base/layout_unittest.cc +++ b/chromium/ui/base/layout_unittest.cc @@ -15,6 +15,7 @@ namespace ui { TEST(LayoutTest, GetScaleFactorScale) { EXPECT_FLOAT_EQ(1.0f, GetScaleFactorScale(SCALE_FACTOR_100P)); + EXPECT_FLOAT_EQ(1.25f, GetScaleFactorScale(SCALE_FACTOR_125P)); EXPECT_FLOAT_EQ(1.33f, GetScaleFactorScale(SCALE_FACTOR_133P)); EXPECT_FLOAT_EQ(1.4f, GetScaleFactorScale(SCALE_FACTOR_140P)); EXPECT_FLOAT_EQ(1.5f, GetScaleFactorScale(SCALE_FACTOR_150P)); @@ -47,8 +48,9 @@ TEST(LayoutTest, GetScaleFactorFromScaleAllSupported) { EXPECT_EQ(SCALE_FACTOR_100P, GetScaleFactorFromScale(0.1f)); EXPECT_EQ(SCALE_FACTOR_100P, GetScaleFactorFromScale(0.9f)); EXPECT_EQ(SCALE_FACTOR_100P, GetScaleFactorFromScale(1.0f)); - EXPECT_EQ(SCALE_FACTOR_133P, GetScaleFactorFromScale(1.19f)); - EXPECT_EQ(SCALE_FACTOR_133P, GetScaleFactorFromScale(1.21f)); + EXPECT_EQ(SCALE_FACTOR_125P, GetScaleFactorFromScale(1.19f)); + EXPECT_EQ(SCALE_FACTOR_125P, GetScaleFactorFromScale(1.21f)); + EXPECT_EQ(SCALE_FACTOR_133P, GetScaleFactorFromScale(1.291f)); EXPECT_EQ(SCALE_FACTOR_133P, GetScaleFactorFromScale(1.3f)); EXPECT_EQ(SCALE_FACTOR_140P, GetScaleFactorFromScale(1.4f)); EXPECT_EQ(SCALE_FACTOR_150P, GetScaleFactorFromScale(1.59f)); diff --git a/chromium/ui/base/models/list_selection_model.h b/chromium/ui/base/models/list_selection_model.h index 95194700852..8a175092ebb 100644 --- a/chromium/ui/base/models/list_selection_model.h +++ b/chromium/ui/base/models/list_selection_model.h @@ -51,7 +51,7 @@ class UI_EXPORT ListSelectionModel { // This is used when a new tab is inserted into the tabstrip. void IncrementFrom(int index); - // Shifts all indices < |index| down by 1. If |index| is selected, it is + // Shifts all indices > |index| down by 1. If |index| is selected, it is // removed. For example, if the selection consists of [0, 1, 5] and this is // invoked with 1, it results in [0, 4]. This is used when a tab is removed // from the tabstrip. diff --git a/chromium/ui/base/models/menu_model.cc b/chromium/ui/base/models/menu_model.cc index c6ddd86f4a7..e88742ebe12 100644 --- a/chromium/ui/base/models/menu_model.cc +++ b/chromium/ui/base/models/menu_model.cc @@ -36,11 +36,11 @@ base::string16 MenuModel::GetSublabelAt(int index) const { return base::string16(); } -const gfx::Font* MenuModel::GetLabelFontAt(int index) const { - return NULL; +base::string16 MenuModel::GetMinorTextAt(int index) const { + return base::string16(); } -const gfx::Font* MenuModel::GetSublabelFontAt(int index) const { +const gfx::Font* MenuModel::GetLabelFontAt(int index) const { return NULL; } diff --git a/chromium/ui/base/models/menu_model.h b/chromium/ui/base/models/menu_model.h index 2af4463d559..bd3730c07b7 100644 --- a/chromium/ui/base/models/menu_model.h +++ b/chromium/ui/base/models/menu_model.h @@ -58,9 +58,13 @@ class UI_EXPORT MenuModel { virtual base::string16 GetLabelAt(int index) const = 0; // Returns the sublabel of the item at the specified index. The sublabel - // is rendered beneath the label and using the font GetSublabelFontAt(). + // is rendered beneath the label and using the font GetLabelFontAt(). virtual base::string16 GetSublabelAt(int index) const; + // Returns the minor text of the item at the specified index. The minor text + // is rendered to the right of the label and using the font GetLabelFontAt(). + virtual base::string16 GetMinorTextAt(int index) const; + // Returns true if the menu item (label/sublabel/icon) at the specified // index can change over the course of the menu's lifetime. If this function // returns true, the label, sublabel and icon of the menu item will be @@ -71,10 +75,6 @@ class UI_EXPORT MenuModel { // If NULL, then the default font should be used. virtual const gfx::Font* GetLabelFontAt(int index) const; - // Returns the font used for the sublabel at the specified index. - // If NULL, then the default font should be used. - virtual const gfx::Font* GetSublabelFontAt(int index) const; - // Gets the acclerator information for the specified index, returning true if // there is a shortcut accelerator for the item, false otherwise. virtual bool GetAcceleratorAt(int index, diff --git a/chromium/ui/base/models/simple_menu_model.cc b/chromium/ui/base/models/simple_menu_model.cc index 2687822f1f9..1ce2d35951e 100644 --- a/chromium/ui/base/models/simple_menu_model.cc +++ b/chromium/ui/base/models/simple_menu_model.cc @@ -17,6 +17,7 @@ struct SimpleMenuModel::Item { int command_id; base::string16 label; base::string16 sublabel; + base::string16 minor_text; gfx::Image icon; ItemType type; int group_id; @@ -47,6 +48,11 @@ base::string16 SimpleMenuModel::Delegate::GetSublabelForCommandId( return base::string16(); } +base::string16 SimpleMenuModel::Delegate::GetMinorTextForCommandId( + int command_id) const { + return base::string16(); +} + bool SimpleMenuModel::Delegate::GetIconForCommandId( int command_id, gfx::Image* image_skia) const { return false; @@ -79,8 +85,8 @@ SimpleMenuModel::~SimpleMenuModel() { } void SimpleMenuModel::AddItem(int command_id, const base::string16& label) { - Item item = { command_id, label, base::string16(), gfx::Image(), - TYPE_COMMAND, -1, NULL, NULL, NORMAL_SEPARATOR }; + Item item = { command_id, label, base::string16(), base::string16(), + gfx::Image(), TYPE_COMMAND, -1, NULL, NULL, NORMAL_SEPARATOR }; AppendItem(item); } @@ -90,8 +96,8 @@ void SimpleMenuModel::AddItemWithStringId(int command_id, int string_id) { void SimpleMenuModel::AddCheckItem(int command_id, const base::string16& label) { - Item item = { command_id, label, base::string16(), gfx::Image(), - TYPE_CHECK, -1, NULL, NULL, NORMAL_SEPARATOR }; + Item item = { command_id, label, base::string16(), base::string16(), + gfx::Image(), TYPE_CHECK, -1, NULL, NULL, NORMAL_SEPARATOR }; AppendItem(item); } @@ -102,8 +108,9 @@ void SimpleMenuModel::AddCheckItemWithStringId(int command_id, int string_id) { void SimpleMenuModel::AddRadioItem(int command_id, const base::string16& label, int group_id) { - Item item = { command_id, label, base::string16(), gfx::Image(), - TYPE_RADIO, group_id, NULL, NULL, NORMAL_SEPARATOR }; + Item item = { command_id, label, base::string16(), base::string16(), + gfx::Image(), TYPE_RADIO, group_id, NULL, NULL, + NORMAL_SEPARATOR }; AppendItem(item); } @@ -127,28 +134,31 @@ void SimpleMenuModel::AddSeparator(MenuSeparatorType separator_type) { if (separator_type != NORMAL_SEPARATOR) NOTIMPLEMENTED(); #endif - Item item = { kSeparatorId, base::string16(), base::string16(), gfx::Image(), - TYPE_SEPARATOR, -1, NULL, NULL , separator_type }; + Item item = { kSeparatorId, base::string16(), base::string16(), + base::string16(), gfx::Image(), TYPE_SEPARATOR, -1, NULL, NULL, + separator_type }; AppendItem(item); } void SimpleMenuModel::RemoveTrailingSeparators() { while (!items_.empty() && items_.back().type == TYPE_SEPARATOR) items_.pop_back(); + MenuItemsChanged(); } void SimpleMenuModel::AddButtonItem(int command_id, ButtonMenuItemModel* model) { - Item item = { command_id, base::string16(), base::string16(), gfx::Image(), - TYPE_BUTTON_ITEM, -1, NULL, model, NORMAL_SEPARATOR }; + Item item = { command_id, base::string16(), base::string16(), + base::string16(), gfx::Image(), TYPE_BUTTON_ITEM, -1, NULL, + model, NORMAL_SEPARATOR }; AppendItem(item); } void SimpleMenuModel::AddSubMenu(int command_id, const base::string16& label, MenuModel* model) { - Item item = { command_id, label, base::string16(), gfx::Image(), - TYPE_SUBMENU, -1, model, NULL, NORMAL_SEPARATOR }; + Item item = { command_id, label, base::string16(), base::string16(), + gfx::Image(), TYPE_SUBMENU, -1, model, NULL, NORMAL_SEPARATOR }; AppendItem(item); } @@ -160,8 +170,8 @@ void SimpleMenuModel::AddSubMenuWithStringId(int command_id, void SimpleMenuModel::InsertItemAt(int index, int command_id, const base::string16& label) { - Item item = { command_id, label, base::string16(), gfx::Image(), - TYPE_COMMAND, -1, NULL, NULL, NORMAL_SEPARATOR }; + Item item = { command_id, label, base::string16(), base::string16(), + gfx::Image(), TYPE_COMMAND, -1, NULL, NULL, NORMAL_SEPARATOR }; InsertItemAtIndex(item, index); } @@ -177,16 +187,17 @@ void SimpleMenuModel::InsertSeparatorAt(int index, NOTIMPLEMENTED(); } #endif - Item item = { kSeparatorId, base::string16(), base::string16(), gfx::Image(), - TYPE_SEPARATOR, -1, NULL, NULL, separator_type }; + Item item = { kSeparatorId, base::string16(), base::string16(), + base::string16(), gfx::Image(), TYPE_SEPARATOR, -1, NULL, NULL, + separator_type }; InsertItemAtIndex(item, index); } void SimpleMenuModel::InsertCheckItemAt(int index, int command_id, const base::string16& label) { - Item item = { command_id, label, base::string16(), gfx::Image(), - TYPE_CHECK, -1, NULL, NULL, NORMAL_SEPARATOR }; + Item item = { command_id, label, base::string16(), base::string16(), + gfx::Image(), TYPE_CHECK, -1, NULL, NULL, NORMAL_SEPARATOR }; InsertItemAtIndex(item, index); } @@ -199,8 +210,9 @@ void SimpleMenuModel::InsertRadioItemAt(int index, int command_id, const base::string16& label, int group_id) { - Item item = { command_id, label, base::string16(), gfx::Image(), - TYPE_RADIO, group_id, NULL, NULL, NORMAL_SEPARATOR }; + Item item = { command_id, label, base::string16(), base::string16(), + gfx::Image(), TYPE_RADIO, group_id, NULL, NULL, + NORMAL_SEPARATOR }; InsertItemAtIndex(item, index); } @@ -214,8 +226,9 @@ void SimpleMenuModel::InsertSubMenuAt(int index, int command_id, const base::string16& label, MenuModel* model) { - Item item = { command_id, label, base::string16(), gfx::Image(), - TYPE_SUBMENU, -1, model, NULL, NORMAL_SEPARATOR }; + Item item = { command_id, label, base::string16(), base::string16(), + gfx::Image(), TYPE_SUBMENU, -1, model, NULL, + NORMAL_SEPARATOR }; InsertItemAtIndex(item, index); } @@ -227,14 +240,22 @@ void SimpleMenuModel::InsertSubMenuWithStringIdAt( void SimpleMenuModel::SetIcon(int index, const gfx::Image& icon) { items_[ValidateItemIndex(index)].icon = icon; + MenuItemsChanged(); } void SimpleMenuModel::SetSublabel(int index, const base::string16& sublabel) { items_[ValidateItemIndex(index)].sublabel = sublabel; + MenuItemsChanged(); +} + +void SimpleMenuModel::SetMinorText(int index, + const base::string16& minor_text) { + items_[ValidateItemIndex(index)].minor_text = minor_text; } void SimpleMenuModel::Clear() { items_.clear(); + MenuItemsChanged(); } int SimpleMenuModel::GetIndexOfCommandId(int command_id) { @@ -285,6 +306,12 @@ base::string16 SimpleMenuModel::GetSublabelAt(int index) const { return items_[ValidateItemIndex(index)].sublabel; } +base::string16 SimpleMenuModel::GetMinorTextAt(int index) const { + if (IsItemDynamicAt(index)) + return delegate_->GetMinorTextForCommandId(GetCommandIdAt(index)); + return items_[ValidateItemIndex(index)].minor_text; +} + bool SimpleMenuModel::IsItemDynamicAt(int index) const { if (delegate_) return delegate_->IsItemForCommandIdDynamic(GetCommandIdAt(index)); @@ -390,6 +417,12 @@ void SimpleMenuModel::OnMenuClosed() { } //////////////////////////////////////////////////////////////////////////////// +// SimpleMenuModel, Protected: + +void SimpleMenuModel::MenuItemsChanged() { +} + +//////////////////////////////////////////////////////////////////////////////// // SimpleMenuModel, Private: int SimpleMenuModel::ValidateItemIndex(int index) const { @@ -401,11 +434,13 @@ int SimpleMenuModel::ValidateItemIndex(int index) const { void SimpleMenuModel::AppendItem(const Item& item) { ValidateItem(item); items_.push_back(item); + MenuItemsChanged(); } void SimpleMenuModel::InsertItemAtIndex(const Item& item, int index) { ValidateItem(item); items_.insert(items_.begin() + index, item); + MenuItemsChanged(); } void SimpleMenuModel::ValidateItem(const Item& item) { diff --git a/chromium/ui/base/models/simple_menu_model.h b/chromium/ui/base/models/simple_menu_model.h index 2204b982fa2..00c93b2a5c9 100644 --- a/chromium/ui/base/models/simple_menu_model.h +++ b/chromium/ui/base/models/simple_menu_model.h @@ -38,10 +38,12 @@ class UI_EXPORT SimpleMenuModel : public MenuModel { int command_id, ui::Accelerator* accelerator) = 0; - // Some command ids have labels, sublabels and icons that change over time. + // Some command ids have labels, sublabels, minor text and icons that change + // over time. virtual bool IsItemForCommandIdDynamic(int command_id) const; virtual base::string16 GetLabelForCommandId(int command_id) const; virtual base::string16 GetSublabelForCommandId(int command_id) const; + virtual base::string16 GetMinorTextForCommandId(int command_id) const; // Gets the icon for the item with the specified id, returning true if there // is an icon, false otherwise. virtual bool GetIconForCommandId(int command_id, @@ -125,6 +127,9 @@ class UI_EXPORT SimpleMenuModel : public MenuModel { // Sets the sublabel for the item at |index|. void SetSublabel(int index, const base::string16& sublabel); + // Sets the minor text for the item at |index|. + void SetMinorText(int index, const base::string16& minor_text); + // Clears all items. Note that it does not free MenuModel of submenu. void Clear(); @@ -140,6 +145,7 @@ class UI_EXPORT SimpleMenuModel : public MenuModel { virtual int GetCommandIdAt(int index) const OVERRIDE; virtual base::string16 GetLabelAt(int index) const OVERRIDE; virtual base::string16 GetSublabelAt(int index) const OVERRIDE; + virtual base::string16 GetMinorTextAt(int index) const OVERRIDE; virtual bool IsItemDynamicAt(int index) const OVERRIDE; virtual bool GetAcceleratorAt(int index, ui::Accelerator* accelerator) const OVERRIDE; @@ -164,6 +170,10 @@ class UI_EXPORT SimpleMenuModel : public MenuModel { void set_delegate(Delegate* delegate) { delegate_ = delegate; } Delegate* delegate() { return delegate_; } + // One or more of the menu menu items associated with the model has changed. + // Do any handling if necessary. + virtual void MenuItemsChanged(); + private: struct Item; diff --git a/chromium/ui/base/resource/resource_bundle.cc b/chromium/ui/base/resource/resource_bundle.cc index 70623c29bc2..31aed58d5bc 100644 --- a/chromium/ui/base/resource/resource_bundle.cc +++ b/chromium/ui/base/resource/resource_bundle.cc @@ -35,6 +35,11 @@ #include "ui/gfx/size_conversions.h" #include "ui/gfx/skbitmap_operations.h" +#if defined(OS_CHROMEOS) +#include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/platform_font_pango.h" +#endif + namespace ui { namespace { @@ -52,6 +57,13 @@ const unsigned char kPngDataChunkType[4] = { 'I', 'D', 'A', 'T' }; ResourceBundle* g_shared_instance_ = NULL; +void InitDefaultFont() { +#if defined(OS_CHROMEOS) + gfx::PlatformFontPango::SetDefaultFontDescription( + l10n_util::GetStringUTF8(IDS_UI_FONT_FAMILY_CROS)); +#endif +} + } // namespace // An ImageSkiaSource that loads bitmaps for the requested scale factor from @@ -118,6 +130,7 @@ std::string ResourceBundle::InitSharedInstanceWithLocale( g_shared_instance_->LoadCommonResources(); std::string result = g_shared_instance_->LoadLocaleResources(pref_locale); + InitDefaultFont(); return result; } @@ -128,6 +141,7 @@ std::string ResourceBundle::InitSharedInstanceLocaleOnly( g_shared_instance_ = new ResourceBundle(delegate); std::string result = g_shared_instance_->LoadLocaleResources(pref_locale); + InitDefaultFont(); return result; } @@ -147,6 +161,7 @@ void ResourceBundle::InitSharedInstanceWithPakFile( return; } g_shared_instance_->locale_resources_data_.reset(data_pack.release()); + InitDefaultFont(); } // static @@ -155,6 +170,8 @@ void ResourceBundle::InitSharedInstanceWithPakPath(const base::FilePath& path) { g_shared_instance_ = new ResourceBundle(NULL); g_shared_instance_->LoadTestResources(path, path); + + InitDefaultFont(); } // static @@ -321,7 +338,7 @@ gfx::Image& ResourceBundle::GetImageNamed(int resource_id) { image = delegate_->GetImageNamed(resource_id); if (image.IsEmpty()) { - DCHECK(!delegate_ && !data_packs_.empty()) << + DCHECK(!data_packs_.empty()) << "Missing call to SetResourcesDataDLL?"; // TODO(oshima): Consider reading the image size from png IHDR chunk and diff --git a/chromium/ui/base/resource/resource_bundle_android.cc b/chromium/ui/base/resource/resource_bundle_android.cc index c701a291252..b1942696603 100644 --- a/chromium/ui/base/resource/resource_bundle_android.cc +++ b/chromium/ui/base/resource/resource_bundle_android.cc @@ -19,8 +19,6 @@ namespace ui { void ResourceBundle::LoadCommonResources() { base::FilePath path; PathService::Get(ui::DIR_RESOURCE_PAKS_ANDROID, &path); - AddDataPackFromPath(path.AppendASCII("chrome.pak"), - SCALE_FACTOR_NONE); AddDataPackFromPath(path.AppendASCII("chrome_100_percent.pak"), SCALE_FACTOR_100P); } diff --git a/chromium/ui/base/resource/resource_bundle_auralinux.cc b/chromium/ui/base/resource/resource_bundle_auralinux.cc index 4bc7ee69665..d5357175a7b 100644 --- a/chromium/ui/base/resource/resource_bundle_auralinux.cc +++ b/chromium/ui/base/resource/resource_bundle_auralinux.cc @@ -33,9 +33,6 @@ void ResourceBundle::LoadCommonResources() { // Always load the 1x data pack first as the 2x data pack contains both 1x and // 2x images. The 1x data pack only has 1x images, thus passes in an accurate // scale factor to gfx::ImageSkia::AddRepresentation. - - AddDataPackFromPath(GetResourcesPakFilePath("chrome.pak"), - SCALE_FACTOR_NONE); AddDataPackFromPath(GetResourcesPakFilePath( "chrome_100_percent.pak"), SCALE_FACTOR_100P); diff --git a/chromium/ui/base/resource/resource_bundle_gtk.cc b/chromium/ui/base/resource/resource_bundle_gtk.cc index 4d16b618e34..2578dc29d37 100644 --- a/chromium/ui/base/resource/resource_bundle_gtk.cc +++ b/chromium/ui/base/resource/resource_bundle_gtk.cc @@ -10,11 +10,11 @@ #include "base/path_service.h" #include "base/synchronization/lock.h" #include "third_party/skia/include/core/SkBitmap.h" -#include "ui/base/gtk/scoped_gobject.h" #include "ui/base/layout.h" #include "ui/base/resource/resource_handle.h" #include "ui/base/ui_base_paths.h" #include "ui/gfx/image/image.h" +#include "ui/gfx/scoped_gobject.h" #include <gtk/gtk.h> @@ -65,8 +65,6 @@ base::FilePath GetResourcesPakFilePath(const std::string& pak_name) { } // namespace void ResourceBundle::LoadCommonResources() { - AddDataPackFromPath(GetResourcesPakFilePath("chrome.pak"), - SCALE_FACTOR_NONE); AddDataPackFromPath(GetResourcesPakFilePath( "chrome_100_percent.pak"), SCALE_FACTOR_100P); diff --git a/chromium/ui/base/resource/resource_bundle_mac.mm b/chromium/ui/base/resource/resource_bundle_mac.mm index 5de8eccc839..56d16d5ed64 100644 --- a/chromium/ui/base/resource/resource_bundle_mac.mm +++ b/chromium/ui/base/resource/resource_bundle_mac.mm @@ -49,8 +49,6 @@ base::FilePath GetResourcesPakFilePath(NSString* name, NSString* mac_locale) { } // namespace void ResourceBundle::LoadCommonResources() { - AddDataPackFromPath(GetResourcesPakFilePath(@"chrome", nil), - SCALE_FACTOR_NONE); AddDataPackFromPath(GetResourcesPakFilePath(@"chrome_100_percent", nil), SCALE_FACTOR_100P); AddDataPackFromPath(GetResourcesPakFilePath(@"webkit_resources_100_percent", diff --git a/chromium/ui/base/resource/resource_bundle_win.cc b/chromium/ui/base/resource/resource_bundle_win.cc index ec47d4c079f..0a2b185e67e 100644 --- a/chromium/ui/base/resource/resource_bundle_win.cc +++ b/chromium/ui/base/resource/resource_bundle_win.cc @@ -10,7 +10,7 @@ #include "ui/base/layout.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/resource/resource_data_dll_win.h" -#include "ui/base/win/dpi.h" +#include "ui/gfx/win/dpi.h" namespace ui { @@ -42,7 +42,7 @@ void ResourceBundle::LoadCommonResources() { // default scaling for Metro mode. If high-DPI mode is enabled, load resource // pak closest to the desired scale factor. The high-DPI resources are // scaled up from 100% touch. - float scale = ui::win::GetDeviceScaleFactor(); + float scale = gfx::win::GetDeviceScaleFactor(); bool force_touch_resources = false; switch(ui::GetScaleFactorFromScale(scale)) { case ui::SCALE_FACTOR_180P: diff --git a/chromium/ui/base/sequential_id_generator.cc b/chromium/ui/base/sequential_id_generator.cc new file mode 100644 index 00000000000..ac3b1a0ed41 --- /dev/null +++ b/chromium/ui/base/sequential_id_generator.cc @@ -0,0 +1,82 @@ +// Copyright (c) 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 "ui/base/sequential_id_generator.h" + +#include "base/logging.h" + +namespace { + +// Removes |key| from |first|, and |first[key]| from |second|. +template<typename T> +void Remove(uint32 key, T* first, T* second) { + typename T::iterator iter = first->find(key); + if (iter == first->end()) + return; + + uint32 second_key = iter->second; + first->erase(iter); + + iter = second->find(second_key); + DCHECK(iter != second->end()); + second->erase(iter); +} + +} // namespace + +namespace ui { + +SequentialIDGenerator::SequentialIDGenerator(uint32 min_id) + : min_id_(min_id), + min_available_id_(min_id) { +} + +SequentialIDGenerator::~SequentialIDGenerator() { +} + +uint32 SequentialIDGenerator::GetGeneratedID(uint32 number) { + IDMap::iterator find = number_to_id_.find(number); + if (find != number_to_id_.end()) + return find->second; + + int id = GetNextAvailableID(); + number_to_id_.insert(std::make_pair(number, id)); + id_to_number_.insert(std::make_pair(id, number)); + return id; +} + +bool SequentialIDGenerator::HasGeneratedIDFor(uint32 number) const { + return number_to_id_.find(number) != number_to_id_.end(); +} + +void SequentialIDGenerator::ReleaseGeneratedID(uint32 id) { + UpdateNextAvailableIDAfterRelease(id); + Remove(id, &id_to_number_, &number_to_id_); +} + +void SequentialIDGenerator::ReleaseNumber(uint32 number) { + DCHECK_GT(number_to_id_.count(number), 0U); + UpdateNextAvailableIDAfterRelease(number_to_id_[number]); + Remove(number, &number_to_id_, &id_to_number_); +} + +uint32 SequentialIDGenerator::GetNextAvailableID() { + const uint32 kMaxID = 128; + while (id_to_number_.count(min_available_id_) > 0 && + min_available_id_ < kMaxID) { + ++min_available_id_; + } + if (min_available_id_ >= kMaxID) + min_available_id_ = min_id_; + return min_available_id_; +} + +void SequentialIDGenerator::UpdateNextAvailableIDAfterRelease(uint32 id) { + if (id < min_available_id_) { + min_available_id_ = id; + DCHECK_GE(min_available_id_, min_id_); + } +} + +} // namespace ui diff --git a/chromium/ui/base/sequential_id_generator.h b/chromium/ui/base/sequential_id_generator.h new file mode 100644 index 00000000000..0adc8bf0c66 --- /dev/null +++ b/chromium/ui/base/sequential_id_generator.h @@ -0,0 +1,60 @@ +// Copyright (c) 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. + +#ifndef UI_BASE_SEQUENTIAL_ID_GENERATOR_H_ +#define UI_BASE_SEQUENTIAL_ID_GENERATOR_H_ + +#include <map> + +#include "base/basictypes.h" +#include "base/containers/hash_tables.h" +#include "ui/base/ui_export.h" + +namespace ui { + +// This is used to generate a series of sequential ID numbers in a way that a +// new ID is always the lowest possible ID in the sequence. +class UI_EXPORT SequentialIDGenerator { + public: + // Creates a new generator with the specified lower bound for the IDs. + explicit SequentialIDGenerator(uint32 min_id); + ~SequentialIDGenerator(); + + // Generates a unique ID to represent |number|. The generated ID is the + // smallest available ID greater than or equal to the |min_id| specified + // during creation of the generator. + uint32 GetGeneratedID(uint32 number); + + // Checks to see if the generator currently has a unique ID generated for + // |number|. + bool HasGeneratedIDFor(uint32 number) const; + + // Removes the generated ID |id| from the internal mapping. Since the ID is + // no longer mapped to any number, subsequent calls to |GetGeneratedID()| can + // use this ID. + void ReleaseGeneratedID(uint32 id); + + // Removes the ID previously generated for |number| by calling + // |GetGeneratedID()|. + void ReleaseNumber(uint32 number); + + private: + typedef base::hash_map<uint32, uint32> IDMap; + + uint32 GetNextAvailableID(); + + void UpdateNextAvailableIDAfterRelease(uint32 id); + + IDMap number_to_id_; + IDMap id_to_number_; + + uint32 min_id_; + uint32 min_available_id_; + + DISALLOW_COPY_AND_ASSIGN(SequentialIDGenerator); +}; + +} // namespace ui + +#endif // UI_BASE_SEQUENTIAL_ID_GENERATOR_H_ diff --git a/chromium/ui/base/sequential_id_generator_unittest.cc b/chromium/ui/base/sequential_id_generator_unittest.cc new file mode 100644 index 00000000000..be703bd7d3f --- /dev/null +++ b/chromium/ui/base/sequential_id_generator_unittest.cc @@ -0,0 +1,62 @@ +// Copyright (c) 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 "ui/base/sequential_id_generator.h" + +#include "base/logging.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace ui { + +typedef testing::Test SequentialIDGeneratorTest; + +TEST(SequentialIDGeneratorTest, AddRemove) { + const uint32 kMinID = 2; + SequentialIDGenerator generator(kMinID); + + EXPECT_EQ(2U, generator.GetGeneratedID(45)); + EXPECT_EQ(3U, generator.GetGeneratedID(23)); + EXPECT_EQ(2U, generator.GetGeneratedID(45)); + EXPECT_TRUE(generator.HasGeneratedIDFor(45)); + EXPECT_TRUE(generator.HasGeneratedIDFor(23)); + + generator.ReleaseGeneratedID(2); + EXPECT_FALSE(generator.HasGeneratedIDFor(45)); + EXPECT_TRUE(generator.HasGeneratedIDFor(23)); + EXPECT_EQ(3U, generator.GetGeneratedID(23)); + + EXPECT_FALSE(generator.HasGeneratedIDFor(1)); + EXPECT_EQ(2U, generator.GetGeneratedID(1)); + EXPECT_TRUE(generator.HasGeneratedIDFor(1)); + + generator.ReleaseGeneratedID(3); + EXPECT_EQ(3U, generator.GetGeneratedID(45)); + EXPECT_TRUE(generator.HasGeneratedIDFor(45)); + + generator.ReleaseNumber(45); + EXPECT_FALSE(generator.HasGeneratedIDFor(45)); +} + +TEST(SequentialIDGeneratorTest, RemoveMultipleNumbers) { + const uint32 kMinID = 4; + SequentialIDGenerator generator(kMinID); + + EXPECT_EQ(4U, generator.GetGeneratedID(45)); + EXPECT_EQ(5U, generator.GetGeneratedID(55)); + EXPECT_EQ(6U, generator.GetGeneratedID(15)); + + generator.ReleaseNumber(45); + EXPECT_FALSE(generator.HasGeneratedIDFor(45)); + generator.ReleaseNumber(15); + EXPECT_FALSE(generator.HasGeneratedIDFor(15)); + + EXPECT_EQ(5U, generator.GetGeneratedID(55)); + EXPECT_EQ(4U, generator.GetGeneratedID(12)); + + generator.ReleaseNumber(12); + generator.ReleaseNumber(55); + EXPECT_EQ(4U, generator.GetGeneratedID(0)); +} + +} // namespace ui diff --git a/chromium/ui/base/strings/app_locale_settings.grd b/chromium/ui/base/strings/app_locale_settings.grd index 2b862d50cb3..d285e9275b0 100644 --- a/chromium/ui/base/strings/app_locale_settings.grd +++ b/chromium/ui/base/strings/app_locale_settings.grd @@ -31,7 +31,13 @@ <output filename="app_locale_settings_eo.pak" type="data_package" lang="eo" /> </if> <output filename="app_locale_settings_es.pak" type="data_package" lang="es" /> - <output filename="app_locale_settings_es-419.pak" type="data_package" lang="es-419" /> + <if expr="is_ios"> + <!-- iOS uses es-MX for es-419 --> + <output filename="app_locale_settings_es-MX.pak" type="data_package" lang="es-419" /> + </if> + <if expr="not is_ios"> + <output filename="app_locale_settings_es-419.pak" type="data_package" lang="es-419" /> + </if> <output filename="app_locale_settings_et.pak" type="data_package" lang="et" /> <if expr="pp_ifdef('use_third_party_translations')"> <output filename="app_locale_settings_eu.pak" type="data_package" lang="eu" /> @@ -75,11 +81,11 @@ be 'nb'. --> <output filename="app_locale_settings_nb.pak" type="data_package" lang="no" /> <output filename="app_locale_settings_pl.pak" type="data_package" lang="pl" /> - <if expr="pp_ifdef('ios')"> + <if expr="is_ios"> <!-- iOS uses pt for pt-BR --> <output filename="app_locale_settings_pt.pak" type="data_package" lang="pt-BR" /> </if> - <if expr="not pp_ifdef('ios')"> + <if expr="not is_ios"> <output filename="app_locale_settings_pt-BR.pak" type="data_package" lang="pt-BR" /> </if> <output filename="app_locale_settings_pt-PT.pak" type="data_package" lang="pt-PT" /> @@ -212,7 +218,7 @@ 75% </message> </if> - <if expr="is_macosx"> + <if expr="is_macosx or is_ios"> <!-- The font used in Web UI (e.g. History). --> <message name="IDS_WEB_FONT_FAMILY" use_name_for_id="true"> 'Lucida Grande', sans-serif diff --git a/chromium/ui/base/strings/app_locale_settings_ja.xtb b/chromium/ui/base/strings/app_locale_settings_ja.xtb index 9edc4a10c8d..1e843b0ad73 100644 --- a/chromium/ui/base/strings/app_locale_settings_ja.xtb +++ b/chromium/ui/base/strings/app_locale_settings_ja.xtb @@ -7,7 +7,7 @@ <translation id="IDS_WEB_FONT_FAMILY">'Segoe UI',Arial,Meiryo,'MS PGothic',sans-serif</translation> <translation id="IDS_WEB_FONT_FAMILY_XP">Arial,Meiryo,'MS PGothic',sans-serif</translation> </if> -<if expr="is_macosx"> +<if expr="is_macosx or is_ios"> <translation id="IDS_WEB_FONT_FAMILY">Helvetica,Hiragino Kaku Gothic Pro,sans-serif</translation> </if> <if expr="is_linux and not pp_ifdef('chromeos')"> diff --git a/chromium/ui/base/strings/app_locale_settings_ko.xtb b/chromium/ui/base/strings/app_locale_settings_ko.xtb index 9d7f042d593..e1db12edb41 100644 --- a/chromium/ui/base/strings/app_locale_settings_ko.xtb +++ b/chromium/ui/base/strings/app_locale_settings_ko.xtb @@ -7,7 +7,7 @@ <translation id="IDS_WEB_FONT_FAMILY">'Segoe UI',Arial,'Malgun Gothic',Gulim,sans-serif</translation> <translation id="IDS_WEB_FONT_FAMILY_XP">Arial,'Malgun Gothic',Gulim,sans-serif</translation> </if> -<if expr="is_macosx"> +<if expr="is_macosx or is_ios"> <translation id="IDS_WEB_FONT_FAMILY">Helvetica,AppleGothic,sans-serif</translation> </if> <if expr="is_linux and not pp_ifdef('chromeos')"> diff --git a/chromium/ui/base/strings/app_locale_settings_zh-CN.xtb b/chromium/ui/base/strings/app_locale_settings_zh-CN.xtb index 6b4c7008649..e67b6c12e12 100644 --- a/chromium/ui/base/strings/app_locale_settings_zh-CN.xtb +++ b/chromium/ui/base/strings/app_locale_settings_zh-CN.xtb @@ -7,7 +7,7 @@ <translation id="IDS_WEB_FONT_FAMILY">'Segoe UI',Arial,'Microsoft Yahei',Simsun,sans-serif</translation> <translation id="IDS_WEB_FONT_FAMILY_XP">Arial,'Microsoft Yahei',Simsun,sans-serif</translation> </if> -<if expr="is_macosx"> +<if expr="is_macosx or is_ios"> <translation id="IDS_WEB_FONT_FAMILY">Helvetica,STHeiti,sans-serif</translation> </if> <if expr="pp_ifdef('chromeos') and pp_ifdef('_google_chrome')"> diff --git a/chromium/ui/base/strings/app_locale_settings_zh-TW.xtb b/chromium/ui/base/strings/app_locale_settings_zh-TW.xtb index 14ae8b0da2b..2492fbc3138 100644 --- a/chromium/ui/base/strings/app_locale_settings_zh-TW.xtb +++ b/chromium/ui/base/strings/app_locale_settings_zh-TW.xtb @@ -7,7 +7,7 @@ <translation id="IDS_WEB_FONT_FAMILY">'Segoe UI',Arial,'Microsoft Jhenghei',PMingLiu,sans-serif</translation> <translation id="IDS_WEB_FONT_FAMILY_XP">Arial,'Microsoft Jhenghei',PMingLiu,sans-serif</translation> </if> -<if expr="is_macosx"> +<if expr="is_macosx or is_ios"> <translation id="IDS_WEB_FONT_FAMILY">Helvetica,LiHei Pro,sans-serif</translation> </if> <if expr="pp_ifdef('chromeos') and pp_ifdef('_google_chrome')"> diff --git a/chromium/ui/base/strings/ui_strings.grd b/chromium/ui/base/strings/ui_strings.grd index ec198ad05f1..590613857ab 100644 --- a/chromium/ui/base/strings/ui_strings.grd +++ b/chromium/ui/base/strings/ui_strings.grd @@ -42,7 +42,13 @@ need to be translated for each locale.--> <output filename="ui_strings_eo.pak" type="data_package" lang="eo" /> </if> <output filename="ui_strings_es.pak" type="data_package" lang="es" /> - <output filename="ui_strings_es-419.pak" type="data_package" lang="es-419" /> + <if expr="is_ios"> + <!-- iOS uses es-MX for es-419 --> + <output filename="ui_strings_es-MX.pak" type="data_package" lang="es-419" /> + </if> + <if expr="not is_ios"> + <output filename="ui_strings_es-419.pak" type="data_package" lang="es-419" /> + </if> <output filename="ui_strings_et.pak" type="data_package" lang="et" /> <if expr="pp_ifdef('use_third_party_translations')"> <output filename="ui_strings_eu.pak" type="data_package" lang="eu" /> @@ -86,11 +92,11 @@ need to be translated for each locale.--> be 'nb'. --> <output filename="ui_strings_nb.pak" type="data_package" lang="no" /> <output filename="ui_strings_pl.pak" type="data_package" lang="pl" /> - <if expr="pp_ifdef('ios')"> + <if expr="is_ios"> <!-- iOS uses pt for pt-BR --> <output filename="ui_strings_pt.pak" type="data_package" lang="pt-BR" /> </if> - <if expr="not pp_ifdef('ios')"> + <if expr="not is_ios"> <output filename="ui_strings_pt-BR.pak" type="data_package" lang="pt-BR" /> </if> <output filename="ui_strings_pt-PT.pak" type="data_package" lang="pt-PT" /> @@ -1458,6 +1464,18 @@ need to be translated for each locale.--> <message name="IDS_APP_PERIOD_KEY" desc="Period key"> Period </message> + <message name="IDS_APP_MEDIA_NEXT_TRACK_KEY" desc="Media next track key"> + Media Next Track + </message> + <message name="IDS_APP_MEDIA_PLAY_PAUSE_KEY" desc="Media play pause key"> + Media Play/Pause + </message> + <message name="IDS_APP_MEDIA_PREV_TRACK_KEY" desc="Media previous track key"> + Media Previous Track + </message> + <message name="IDS_APP_MEDIA_STOP_KEY" desc="Media stop key"> + Media Stop + </message> <!-- Shortcut Modifiers --> <message name="IDS_APP_CONTROL_MODIFIER" desc="Control key shortcut modifier"> @@ -1515,11 +1533,8 @@ need to be translated for each locale.--> <message name="IDS_MESSAGE_CENTER_ACCESSIBLE_NAME" desc="The accessible name for the Notification Center window."> Notification Center </message> - <message name="IDS_MESSAGE_CENTER_EXTENSIONS_DISABLE" desc="The menu entry for disabling extensions from a notification."> - Disable notifications from <ph name="extension_name">$1<ex>Notification Galore!</ex></ph> - </message> - <message name="IDS_MESSAGE_CENTER_SITE_DISABLE" desc="The menu entry for disabling notification from a site."> - Disable notifications from <ph name="site">$1<ex>mail.google.com</ex></ph> + <message name="IDS_MESSAGE_CENTER_NOTIFIER_DISABLE" desc="The menu entry for disabling a notifier from a notification."> + Disable notifications from <ph name="notifier_name">$1<ex>Notification Galore!</ex></ph> </message> <message name="IDS_MESSAGE_CENTER_FOOTER_TITLE" desc="The label in the footer of the message center"> Notifications diff --git a/chromium/ui/base/strings/ui_strings_am.xtb b/chromium/ui/base/strings/ui_strings_am.xtb index d3576a6c805..81d224ae737 100644 --- a/chromium/ui/base/strings/ui_strings_am.xtb +++ b/chromium/ui/base/strings/ui_strings_am.xtb @@ -6,16 +6,17 @@ <translation id="6135826906199951471">Del</translation> <translation id="528468243742722775">ጨርስ</translation> <translation id="5341849548509163798">ከ<ph name="NUMBER_MANY"/> ሰዓቶች በፊት</translation> -<translation id="6310545596129886942"><ph name="NUMBER_FEW"/> ሰከንድ ይቀራል</translation> -<translation id="9213479837033539041"><ph name="NUMBER_MANY"/> ሰከንድ ይቀራል</translation> +<translation id="6310545596129886942"><ph name="NUMBER_FEW"/> ሴኮንድ ይቀራል</translation> +<translation id="9213479837033539041"><ph name="NUMBER_MANY"/> ሴኮንድ ይቀራል</translation> <translation id="1209866192426315618"><ph name="NUMBER_DEFAULT"/> ደቂቃ ይቀራል</translation> <translation id="1801827354178857021">ነቁጥ</translation> <translation id="1190609913194133056">የማሳወቂያ ማዕከል</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> ደቂቃዎች ቀርተዋል</translation> <translation id="5613020302032141669">ግራ ቀስት</translation> +<translation id="4971687151119236543">የሚዲያ ቀዳሚ ትራክ</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> ፋይል(.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918">ከ<ph name="NUMBER_ZERO"/> ደቂቃ በፊት</translation> -<translation id="7121570032414343252"><ph name="NUMBER_TWO"/> ሰከንድ</translation> +<translation id="7121570032414343252"><ph name="NUMBER_TWO"/> ሴኮንድ</translation> <translation id="7511635910912978956"><ph name="NUMBER_FEW"/> ሰዓቶች ይቀራሉ</translation> <translation id="5948410903763073882">Alt+<ph name="KEY_COMBO_NAME"/></translation> <translation id="7658239707568436148">ሰርዝ</translation> @@ -30,7 +31,7 @@ <translation id="932327136139879170">መነሻ</translation> <translation id="5600907569873192868"><ph name="NUMBER_MANY"/> ደቂቃ ይቀራል</translation> <translation id="8666066831007952346"><ph name="NUMBER_TWO"/> ቀናት ይቀራሉ</translation> -<translation id="6390842777729054533">ከ<ph name="NUMBER_ZERO"/> ሰከንድ በፊት</translation> +<translation id="6390842777729054533">ከ<ph name="NUMBER_ZERO"/> ሴኮንድ በፊት</translation> <translation id="3909791450649380159">&ቁረጥ</translation> <translation id="2560788951337264832"><ph name="NUMBER_ZERO"/> ደቂቃዎች ቀርተዋል</translation> <translation id="688711909580084195">ርዕስ-አልባ ድረ-ገጽ</translation> @@ -58,10 +59,10 @@ <translation id="1572103024875503863"><ph name="NUMBER_MANY"/> ቀናት</translation> <translation id="7163503212501929773"><ph name="NUMBER_MANY"/> ሰዓቶች ይቀራሉ</translation> <translation id="5329858601952122676">&ሠርዝ</translation> -<translation id="8088823334188264070"><ph name="NUMBER_MANY"/> ሰከንድ</translation> +<translation id="8088823334188264070"><ph name="NUMBER_MANY"/> ሴኮንድ</translation> <translation id="8901569739625249689"><ph name="QUANTITY"/> ኪባ</translation> <translation id="7712011264267466734"><ph name="NUMBER_MANY"/> ደቂቃዎች</translation> -<translation id="7275974018215686543">ከ<ph name="NUMBER_MANY"/> ሰከንድ በፊት</translation> +<translation id="7275974018215686543">ከ<ph name="NUMBER_MANY"/> ሴኮንድ በፊት</translation> <translation id="7781829728241885113">ትናንት</translation> <translation id="3424538384153559412"><ph name="NUMBER_TWO"/> ደቂቃዎች</translation> <translation id="50960180632766478"><ph name="NUMBER_FEW"/> ደቂቃ ይቀራል</translation> @@ -72,11 +73,11 @@ <translation id="2497284189126895209">ሁሉም ፋይሎች</translation> <translation id="7487278341251176613"><ph name="NUMBER_TWO"/> ደቂቃዎች ቀርተዋል</translation> <translation id="5110450810124758964">ከ<ph name="NUMBER_ONE"/> ቀን በፊት</translation> -<translation id="2820806154655529776"><ph name="NUMBER_ONE"/> ሰከንድ</translation> +<translation id="2820806154655529776"><ph name="NUMBER_ONE"/> ሴኮንድ</translation> <translation id="7814458197256864873">&ቅዳ</translation> <translation id="3889424535448813030">ቀኝ ቀስት</translation> -<translation id="4229495110203539533">ከ<ph name="NUMBER_ONE"/> ሰከንድ በፊት</translation> -<translation id="2544782972264605588">ከ<ph name="NUMBER_DEFAULT"/> ሰከንድ በፊት</translation> +<translation id="4229495110203539533">ከ<ph name="NUMBER_ONE"/> ሴኮንድ በፊት</translation> +<translation id="2544782972264605588">ከ<ph name="NUMBER_DEFAULT"/> ሴኮንድ በፊት</translation> <translation id="6829324100069873704">ወደ ማሳወቂያዎች ተመለስ።</translation> <translation id="6528179044667508675">አትረብሽ</translation> <translation id="5066177358602611309"><ph name="NUMBER_DEFAULT"/> ሰከንዶች</translation> @@ -95,7 +96,7 @@ <translation id="9107059250669762581"><ph name="NUMBER_DEFAULT"/> ቀን</translation> <translation id="6463061331681402734"><ph name="NUMBER_MANY"/> ደቂቃ</translation> <translation id="7634624804467787019"><ph name="NUMBER_ONE"/> ደቂቃ</translation> -<translation id="8448317557906454022">ከ<ph name="NUMBER_ZERO"/> ሰከንድ በፊት</translation> +<translation id="8448317557906454022">ከ<ph name="NUMBER_ZERO"/> ሴኮንድ በፊት</translation> <translation id="4927753642311223124">እዚህ ምንም የሚታይ ነገር የለም፣ ይቀጥሉ።</translation> <translation id="2482878487686419369">ማስታወቂያዎች</translation> <translation id="6357135709975569075"><ph name="NUMBER_ZERO"/> ቀን</translation> @@ -104,24 +105,26 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> ሰዓቶች</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> ኪባ/ሰ</translation> +<translation id="8394908167088220973">ሚዲያ አጫውት/ለአፍታ አቁም</translation> <translation id="2148716181193084225">ዛሬ</translation> <translation id="7960078400008666149">ለአንድ ሰዓት አትረብሽ</translation> <translation id="4373894838514502496">ከ<ph name="NUMBER_FEW"/> ደቂቃ በፊት</translation> <translation id="4115153316875436289"><ph name="NUMBER_TWO"/> ቀናት</translation> <translation id="2190355936436201913">(ባዶ)</translation> <translation id="1164369517022005061"><ph name="NUMBER_DEFAULT"/> ሰዓት ይቀራል</translation> -<translation id="152482086482215392"><ph name="NUMBER_ONE"/> ሰከንድ ይቀራል</translation> +<translation id="152482086482215392"><ph name="NUMBER_ONE"/> ሴኮንድ ይቀራል</translation> <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">ወደ ቀኝ ሸብልል</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> ሰዓት ይቀራል</translation> +<translation id="1413622004203049571">ከ<ph name="NOTIFIER_NAME"/> የሚመጡ ማሳወቂያዎችን አሰናክል</translation> <translation id="2666092431469916601">ላይ</translation> <translation id="8331626408530291785">ወደ ላይ ሸብልል</translation> -<translation id="4773379706300191099">የ<ph name="EXTENSION_NAME"/> ማሳወቂያዎችን አሰናክል</translation> <translation id="7907591526440419938">ፋይል ክፈት</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> ቀን ይቀራል</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045">ከ<ph name="NUMBER_DEFAULT"/> ሰዓት በፊት</translation> <translation id="815598010540052116">ወደ ታች ሸብልል</translation> +<translation id="6808150112686056157">ሚዲያ አቁም</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> ደቂቃ ይቀራል</translation> <translation id="3157931365184549694">እነበረበት መልስ</translation> <translation id="1243314992276662751">ስቀል</translation> @@ -131,14 +134,14 @@ <translation id="9170848237812810038">&ቀልብስ</translation> <translation id="1285266685456062655">ከ<ph name="NUMBER_FEW"/> ሰዓቶች በፊት</translation> <translation id="6918245111648057970">ከሚከተሉት ውስጥ ለእያንዳንዱ ተጠቃሚ ማሳወቂያዎችን ይፍቀዱ፦</translation> -<translation id="5489830104927132166"><ph name="NUMBER_ONE"/> ሰከንድ</translation> +<translation id="5489830104927132166"><ph name="NUMBER_ONE"/> ሴኮንድ</translation> <translation id="3994835489895548312"><ph name="NUMBER_MANY"/> ደቂቃዎች ቀርተዋል</translation> -<translation id="6358975074282722691">ከ<ph name="NUMBER_TWO"/> ሰከንድ በፊት</translation> +<translation id="6358975074282722691">ከ<ph name="NUMBER_TWO"/> ሴኮንድ በፊት</translation> <translation id="520299402983819650"><ph name="QUANTITY"/> ፔታ</translation> <translation id="2983818520079887040">ቅንብሮች ...</translation> <translation id="6845383723252244143">አቃፊ ምረጥ</translation> <translation id="7600770490873519066"><ph name="NUMBER_FEW"/> ሰከንዶች</translation> -<translation id="1095623615273566396"><ph name="NUMBER_FEW"/> ሰከንድ</translation> +<translation id="1095623615273566396"><ph name="NUMBER_FEW"/> ሴኮንድ</translation> <translation id="5583640892426849032">Backspace</translation> <translation id="5263972071113911534">ከ<ph name="NUMBER_MANY"/> ቀናት በፊት</translation> <translation id="8355915647418390920"><ph name="NUMBER_FEW"/> ቀናት</translation> @@ -147,11 +150,11 @@ <translation id="8788572795284305350">ከ<ph name="NUMBER_ZERO"/> ሰዓት በፊት</translation> <translation id="3740362395218339114"><ph name="QUANTITY"/> ጊባ/ሰ</translation> <translation id="6644971472240498405"><ph name="NUMBER_ONE"/> ቀን</translation> -<translation id="9098468523912235228">ከ<ph name="NUMBER_DEFAULT"/> ሰከንድ በፊት</translation> -<translation id="494645311413743213"><ph name="NUMBER_TWO"/> ሰከንድ ይቀራል</translation> +<translation id="9098468523912235228">ከ<ph name="NUMBER_DEFAULT"/> ሴኮንድ በፊት</translation> +<translation id="494645311413743213"><ph name="NUMBER_TWO"/> ሴኮንድ ይቀራል</translation> <translation id="4570886800634958009">ማሳወቂያ ዘርጋ</translation> <translation id="436869212180315161">ተጫን</translation> -<translation id="4860787810836767172">ከ<ph name="NUMBER_FEW"/> ሰከንድ በፊት</translation> +<translation id="4860787810836767172">ከ<ph name="NUMBER_FEW"/> ሴኮንድ በፊት</translation> <translation id="2297836609126180313"><ph name="QUANTITY"/> ቴባ/ሰ</translation> <translation id="6956540737482608074"><ph name="NUMBER_ZERO"/> ደቂቃዎች</translation> <translation id="1858722859751911017"><ph name="NUMBER_FEW"/> ደቂቃዎች ቀርተዋል</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497">ከ<ph name="NUMBER_MANY"/> ደቂቃ በፊት</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> ባ/ሰ</translation> <translation id="7649070708921625228">እገዛ</translation> +<translation id="6699343763173986273">የሚዲያ ቀጣይ ትራክ</translation> <translation id="8226233771743600312">ለአንድ ቀን አትረብሽ</translation> <translation id="7457942297256758195">ሁሉንም አጽዳ</translation> <translation id="822618367988303761">ከ<ph name="NUMBER_TWO"/> ቀናት በፊት</translation> @@ -168,8 +172,8 @@ <translation id="5906719743126878045"><ph name="NUMBER_TWO"/> ሰዓቶች ይቀራሉ</translation> <translation id="8959208747503200525">ከ<ph name="NUMBER_TWO"/> ሰዓቶች በፊት</translation> <translation id="8400147561352026160">Shift+<ph name="KEY_COMBO_NAME"/></translation> -<translation id="8421864404045570940"><ph name="NUMBER_DEFAULT"/> ሰከንድ</translation> -<translation id="4197700912384709145"><ph name="NUMBER_ZERO"/> ሰከንድ</translation> +<translation id="8421864404045570940"><ph name="NUMBER_DEFAULT"/> ሴኮንድ</translation> +<translation id="4197700912384709145"><ph name="NUMBER_ZERO"/> ሴኮንድ</translation> <translation id="27199337101878275"><ph name="NUMBER_MANY"/> ሰከንዶች</translation> <translation id="3759876923365568382"><ph name="NUMBER_FEW"/> ቀን ይቀራል</translation> <translation id="6907759265145635167"><ph name="QUANTITY"/> ፔባ/ሰ</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496">ከ<ph name="NUMBER_ZERO"/> ቀን በፊት</translation> <translation id="5941711191222866238">አሳንስ</translation> <translation id="6394627529324717982">ኮማ</translation> -<translation id="4469842253116033348">ማስታወቂያዎችን ከ<ph name="SITE"/> አሰናክል</translation> <translation id="3036649622769666520">ፋይሎች ክፈት</translation> <translation id="8328145009876646418">የግራ ጠርዝ</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> ሰከንዶች</translation> diff --git a/chromium/ui/base/strings/ui_strings_ar.xtb b/chromium/ui/base/strings/ui_strings_ar.xtb index d9769f3f4bb..29d95e82cc9 100644 --- a/chromium/ui/base/strings/ui_strings_ar.xtb +++ b/chromium/ui/base/strings/ui_strings_ar.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">مركز الإشعارات</translation> <translation id="7470933019269157899">عدد الدقائق المتبقية: <ph name="NUMBER_DEFAULT"/></translation> <translation id="5613020302032141669">مفتاح سهم إلى اليسار</translation> +<translation id="4971687151119236543">المقطع الصوتي السابق للوسائط</translation> <translation id="8602707065186045623">ملف <ph name="SAVEAS_EXTENSION_TYPE"/> (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918">قبل <ph name="NUMBER_ZERO"/> دقيقة</translation> <translation id="7121570032414343252">عدد الثواني: <ph name="NUMBER_TWO"/></translation> @@ -97,13 +98,14 @@ <translation id="7634624804467787019"><ph name="NUMBER_ONE"/> دقيقة واحدة</translation> <translation id="8448317557906454022">قبل <ph name="NUMBER_ZERO"/> ثانية</translation> <translation id="4927753642311223124">ليس هناك شيء تراه هنا، انتقل إلى مكان آخر.</translation> -<translation id="2482878487686419369">التنبيهات</translation> +<translation id="2482878487686419369">الاشعارات</translation> <translation id="6357135709975569075"><ph name="NUMBER_ZERO"/> يوم</translation> <translation id="3183922693828471536">التمرير إلى هنا</translation> <translation id="4552416320897244156">مفتاح PgDwn (صفحة إلى أسفل)</translation> <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> ساعة</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> كيلوبايت/ثانية</translation> +<translation id="8394908167088220973">تشغيل/إيقاف الوسائط</translation> <translation id="2148716181193084225">اليوم</translation> <translation id="7960078400008666149">الرجاء عدم الإزعاج لمدة ساعة واحدة</translation> <translation id="4373894838514502496">قبل <ph name="NUMBER_FEW"/> دقيقة</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">مفتاح PgUp (صفحة إلى أعلى)</translation> <translation id="4588090240171750605">التمرير إلى اليسار</translation> <translation id="7414887922320653780">عدد الساعات المتبقية: <ph name="NUMBER_ONE"/></translation> +<translation id="1413622004203049571">تعطيل الإشعارات من <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">أعلى</translation> <translation id="8331626408530291785">التمرير إلى أعلى</translation> -<translation id="4773379706300191099">تعطيل الإشعارات من <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">فتح ملف</translation> <translation id="2864069933652346933">متبقٍ <ph name="NUMBER_ZERO"/> يوم</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045">قبل <ph name="NUMBER_DEFAULT"/> ساعة</translation> <translation id="815598010540052116">التمرير إلى أسفل</translation> +<translation id="6808150112686056157">إيقاف الوسائط</translation> <translation id="1308727876662951186">متبقٍ <ph name="NUMBER_ZERO"/> دقيقة</translation> <translation id="3157931365184549694">استعادة</translation> <translation id="1243314992276662751">تحميل</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497">قبل <ph name="NUMBER_MANY"/> دقيقة</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> بايت/ثانية</translation> <translation id="7649070708921625228">مساعدة</translation> +<translation id="6699343763173986273">المقطع الصوتي التالي للوسائط</translation> <translation id="8226233771743600312">الرجاء عدم الإزعاج لمدة يوم واحد</translation> <translation id="7457942297256758195">محو الكل</translation> <translation id="822618367988303761">قبل <ph name="NUMBER_TWO"/> يوم</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496">قبل <ph name="NUMBER_ZERO"/> يوم</translation> <translation id="5941711191222866238">تصغير</translation> <translation id="6394627529324717982">فاصلة</translation> -<translation id="4469842253116033348">تعطيل التنبيهات من الموقع <ph name="SITE"/></translation> <translation id="3036649622769666520">فتح الملفات</translation> <translation id="8328145009876646418">الحافة اليمنى</translation> <translation id="7372005818821648611">ثانيتان (<ph name="NUMBER_TWO"/>)</translation> diff --git a/chromium/ui/base/strings/ui_strings_bg.xtb b/chromium/ui/base/strings/ui_strings_bg.xtb index 859ba008b87..427b3abfe9f 100644 --- a/chromium/ui/base/strings/ui_strings_bg.xtb +++ b/chromium/ui/base/strings/ui_strings_bg.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Център за известия</translation> <translation id="7470933019269157899">Остават <ph name="NUMBER_DEFAULT"/> минути</translation> <translation id="5613020302032141669">Стрелка наляво</translation> +<translation id="4971687151119236543">Мултимедия, предишният запис</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> файл (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> сек</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> часа</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> КБ/сек</translation> +<translation id="8394908167088220973">Мултимедия, пускане/пауза</translation> <translation id="2148716181193084225">Днес</translation> <translation id="7960078400008666149">Не безпокойте за един час</translation> <translation id="4373894838514502496">преди <ph name="NUMBER_FEW"/> мин</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Превъртане надясно</translation> <translation id="7414887922320653780">Остава <ph name="NUMBER_ONE"/> час</translation> +<translation id="1413622004203049571">Деактивиране на известията от <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Най-горе</translation> <translation id="8331626408530291785">Превъртане нагоре</translation> -<translation id="4773379706300191099">Деактивиране на известията от <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Отваряне на файл</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045">преди <ph name="NUMBER_DEFAULT"/> часа</translation> <translation id="815598010540052116">Превъртане надолу</translation> +<translation id="6808150112686056157">Мултимедия, стоп</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Възстановяване</translation> <translation id="1243314992276662751">Качване</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497">преди <ph name="NUMBER_MANY"/> мин</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> Б/сек</translation> <translation id="7649070708921625228">Помощ</translation> +<translation id="6699343763173986273">Мултимедия, следващият запис</translation> <translation id="8226233771743600312">Не безпокойте за един ден</translation> <translation id="7457942297256758195">Изчистване на всички</translation> <translation id="822618367988303761">преди <ph name="NUMBER_TWO"/> дни</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Намаляване</translation> <translation id="6394627529324717982">Запетая</translation> -<translation id="4469842253116033348">Деактивиране на известията от <ph name="SITE"/></translation> <translation id="3036649622769666520">Отваряне на файлове</translation> <translation id="8328145009876646418">Ляв край</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> секунди</translation> diff --git a/chromium/ui/base/strings/ui_strings_bn.xtb b/chromium/ui/base/strings/ui_strings_bn.xtb index 2466e539ce5..de6f7dc3984 100644 --- a/chromium/ui/base/strings/ui_strings_bn.xtb +++ b/chromium/ui/base/strings/ui_strings_bn.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">বিজ্ঞপ্তি কেন্দ্র</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> মিনিট বাকি</translation> <translation id="5613020302032141669">Left Arrow</translation> +<translation id="4971687151119236543">মিডিয়া পূর্ববর্তী ট্র্যাক</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> ফাইল (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> সেকেন্ড</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> ঘন্টা</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">মিডিয়া প্লে করুন/বিরতি</translation> <translation id="2148716181193084225">আজ</translation> <translation id="7960078400008666149">এক ঘন্টার জন্য বিরক্ত করবেন না</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> mins ago</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">ডান দিকে স্ক্রোল করুন</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> ঘন্টা বাকি</translation> +<translation id="1413622004203049571"><ph name="NOTIFIER_NAME"/> এর থেকে বিজ্ঞপ্তিগুলি অক্ষম করুন</translation> <translation id="2666092431469916601">শীর্ষ</translation> <translation id="8331626408530291785">উপরে স্ক্রোল করুন</translation> -<translation id="4773379706300191099"><ph name="EXTENSION_NAME"/> থেকে বিজ্ঞপ্তিগুলি অক্ষম করুন</translation> <translation id="7907591526440419938">খোলা ফাইল</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> ঘন্টা আগে</translation> <translation id="815598010540052116">নীচে স্ক্রোল করুন</translation> +<translation id="6808150112686056157">মিডিয়া থামান</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">পুনরুদ্ধার করুন</translation> <translation id="1243314992276662751">আপলোড</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">সহায়তা</translation> +<translation id="6699343763173986273">মিডিয়া পরবর্তী ট্র্যাক</translation> <translation id="8226233771743600312">এক দিনের জন্য বিরক্ত করবেন না</translation> <translation id="7457942297256758195">সমস্ত সাফ করুন</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">ছোট করুন</translation> <translation id="6394627529324717982">কমা</translation> -<translation id="4469842253116033348"><ph name="SITE"/>-এর থেকে বিজ্ঞপ্তি অক্ষম করুন</translation> <translation id="3036649622769666520">খোলা ফাইল</translation> <translation id="8328145009876646418">বাম প্রান্ত</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> সেকেন্ড</translation> diff --git a/chromium/ui/base/strings/ui_strings_ca.xtb b/chromium/ui/base/strings/ui_strings_ca.xtb index d07f75bcad8..4f61bb41fae 100644 --- a/chromium/ui/base/strings/ui_strings_ca.xtb +++ b/chromium/ui/base/strings/ui_strings_ca.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Centre de notificacions</translation> <translation id="7470933019269157899">Queden <ph name="NUMBER_DEFAULT"/> minuts</translation> <translation id="5613020302032141669">Fletxa esquerra</translation> +<translation id="4971687151119236543">Fitxer multimèdia: pista anterior</translation> <translation id="8602707065186045623">Fitxer <ph name="SAVEAS_EXTENSION_TYPE"/> (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> segons</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> hores</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">Fitxer multimèdia: reprodueix/posa en pausa</translation> <translation id="2148716181193084225">Avui</translation> <translation id="7960078400008666149">No molesteu durant una hora</translation> <translation id="4373894838514502496">Fa <ph name="NUMBER_FEW"/> minuts</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">Re Pàg</translation> <translation id="4588090240171750605">Desplaçament a la dreta</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> hores restants</translation> +<translation id="1413622004203049571">Desactiva les notificacions de <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Superior</translation> <translation id="8331626408530291785">Desplaçament amunt</translation> -<translation id="4773379706300191099">Desactiva les notificacions de <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Obre un fitxer</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045">Fa <ph name="NUMBER_DEFAULT"/> hores</translation> <translation id="815598010540052116">Desplaçament avall</translation> +<translation id="6808150112686056157">Fitxer multimèdia: atura</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Restaura</translation> <translation id="1243314992276662751">Penja</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497">Fa <ph name="NUMBER_MANY"/> minuts</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Ajuda</translation> +<translation id="6699343763173986273">Fitxer multimèdia: pista següent</translation> <translation id="8226233771743600312">No molesteu durant un dia</translation> <translation id="7457942297256758195">Esborra-ho tot</translation> <translation id="822618367988303761">Fa <ph name="NUMBER_TWO"/> dies</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Minimitza</translation> <translation id="6394627529324717982">Coma</translation> -<translation id="4469842253116033348">Desactiva les notificacions de <ph name="SITE"/></translation> <translation id="3036649622769666520">Obre fitxers</translation> <translation id="8328145009876646418">Extrem esquerre</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> segons</translation> diff --git a/chromium/ui/base/strings/ui_strings_cs.xtb b/chromium/ui/base/strings/ui_strings_cs.xtb index d6882c7751c..b6e4dcc291a 100644 --- a/chromium/ui/base/strings/ui_strings_cs.xtb +++ b/chromium/ui/base/strings/ui_strings_cs.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Centrum oznámení</translation> <translation id="7470933019269157899">Zbývá <ph name="NUMBER_DEFAULT"/> min</translation> <translation id="5613020302032141669">Klávesa šipka vlevo</translation> +<translation id="4971687151119236543">Média – předchozí skladba</translation> <translation id="8602707065186045623">Soubor <ph name="SAVEAS_EXTENSION_TYPE"/> (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> s</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> hod</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> kB/s</translation> +<translation id="8394908167088220973">Média – přehrát/pozastavit</translation> <translation id="2148716181193084225">Dnes</translation> <translation id="7960078400008666149">Nerušit jednu hodinu</translation> <translation id="4373894838514502496">před <ph name="NUMBER_FEW"/> minutami</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">Klávesa PgUp</translation> <translation id="4588090240171750605">Posuv doprava</translation> <translation id="7414887922320653780">Zbývá: <ph name="NUMBER_ONE"/> hod</translation> +<translation id="1413622004203049571">Deaktivovat oznámení ze služby <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Nahoru</translation> <translation id="8331626408530291785">Posuv nahoru</translation> -<translation id="4773379706300191099">Deaktivovat oznámení rozšíření <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Otevřít soubor</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Klávesa Esc</translation> <translation id="2797524280730715045">Před <ph name="NUMBER_DEFAULT"/> hodinami</translation> <translation id="815598010540052116">Posuv dolů</translation> +<translation id="6808150112686056157">Média – zastavit</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Obnovit</translation> <translation id="1243314992276662751">Nahrát</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Nápověda</translation> +<translation id="6699343763173986273">Média – další skladba</translation> <translation id="8226233771743600312">Nerušit jeden den</translation> <translation id="7457942297256758195">Vymazat vše</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Minimalizovat</translation> <translation id="6394627529324717982">Čárka</translation> -<translation id="4469842253116033348">Deaktivovat oznámení z webu <ph name="SITE"/></translation> <translation id="3036649622769666520">Otevřít soubory</translation> <translation id="8328145009876646418">Levý okraj</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> s</translation> diff --git a/chromium/ui/base/strings/ui_strings_da.xtb b/chromium/ui/base/strings/ui_strings_da.xtb index abd0fe6edf9..8befca3e7e5 100644 --- a/chromium/ui/base/strings/ui_strings_da.xtb +++ b/chromium/ui/base/strings/ui_strings_da.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Underretningcenter</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> minutter tilbage</translation> <translation id="5613020302032141669">Venstrepil</translation> +<translation id="4971687151119236543">Medie: Forrige nummer</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> Fil (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> sek.</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> timer</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> kB/sek.</translation> +<translation id="8394908167088220973">Medie: Afspil/Pause</translation> <translation id="2148716181193084225">I dag</translation> <translation id="7960078400008666149">Vil ikke forstyrres i en time</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> minutter siden</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Scroll til højre</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> timer tilbage</translation> +<translation id="1413622004203049571">Deaktiver underretninger fra <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Top</translation> <translation id="8331626408530291785">Scroll Up</translation> -<translation id="4773379706300191099">Deaktiver underretninger fra <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Åbn fil</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> timer siden</translation> <translation id="815598010540052116">Scroll Down</translation> +<translation id="6808150112686056157">Medie: Stop</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Gendan</translation> <translation id="1243314992276662751">Upload</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> minutter siden</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/sek.</translation> <translation id="7649070708921625228">Hjælp</translation> +<translation id="6699343763173986273">Medie: Næste nummer</translation> <translation id="8226233771743600312">Vil ikke forstyrres i et døgn</translation> <translation id="7457942297256758195">Ryd alle</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> dage siden</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Minimer</translation> <translation id="6394627529324717982">Komma</translation> -<translation id="4469842253116033348">Deaktiver meddelelser fra <ph name="SITE"/></translation> <translation id="3036649622769666520">Åbn filer</translation> <translation id="8328145009876646418">Venstre kant</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> sekunder</translation> diff --git a/chromium/ui/base/strings/ui_strings_de.xtb b/chromium/ui/base/strings/ui_strings_de.xtb index df63bb041ac..b2ba42282d1 100644 --- a/chromium/ui/base/strings/ui_strings_de.xtb +++ b/chromium/ui/base/strings/ui_strings_de.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Benachrichtigungscenter</translation> <translation id="7470933019269157899">Noch <ph name="NUMBER_DEFAULT"/> Minuten</translation> <translation id="5613020302032141669">Linkspfeil</translation> +<translation id="4971687151119236543">Medien – vorheriger Titel</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/>-Datei (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> Sekunden</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> Stunden</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">Medien – Wiedergabe/Pause</translation> <translation id="2148716181193084225">Heute</translation> <translation id="7960078400008666149">1 Stunde nicht stören</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> mins ago</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">BildAuf</translation> <translation id="4588090240171750605">Nach rechts blättern</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> Stunde übrig</translation> +<translation id="1413622004203049571">Benachrichtigungen von <ph name="NOTIFIER_NAME"/> deaktivieren</translation> <translation id="2666092431469916601">Oben</translation> <translation id="8331626408530291785">Nach oben blättern</translation> -<translation id="4773379706300191099">Benachrichtigungen von <ph name="EXTENSION_NAME"/> deaktivieren</translation> <translation id="7907591526440419938">Datei öffnen</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045">Vor <ph name="NUMBER_DEFAULT"/> Stunden</translation> <translation id="815598010540052116">Nach unten blättern</translation> +<translation id="6808150112686056157">Medien – Stopp</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Wiederherstellen</translation> <translation id="1243314992276662751">Hochladen</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> Byte/s</translation> <translation id="7649070708921625228">Hilfe</translation> +<translation id="6699343763173986273">Medien – nächster Titel</translation> <translation id="8226233771743600312">1 Tag nicht stören</translation> <translation id="7457942297256758195">Alle löschen</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Verkleinern</translation> <translation id="6394627529324717982">Komma</translation> -<translation id="4469842253116033348">Benachrichtigungen von <ph name="SITE"/> deaktivieren</translation> <translation id="3036649622769666520">Dateien öffnen</translation> <translation id="8328145009876646418">Linker Rand</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> Sekunden</translation> diff --git a/chromium/ui/base/strings/ui_strings_el.xtb b/chromium/ui/base/strings/ui_strings_el.xtb index 7fbfbf0c735..3cb7bdfcfe1 100644 --- a/chromium/ui/base/strings/ui_strings_el.xtb +++ b/chromium/ui/base/strings/ui_strings_el.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Κέντρο ειδοποιήσεων</translation> <translation id="7470933019269157899">Υπολείπονται <ph name="NUMBER_DEFAULT"/> λεπτά</translation> <translation id="5613020302032141669">Αριστερό βέλος</translation> +<translation id="4971687151119236543">Προηγούμενο κομμάτι πολυμέσων</translation> <translation id="8602707065186045623">Αρχείο <ph name="SAVEAS_EXTENSION_TYPE"/> (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> δευτερόλεπτα</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">Πλήκτρο F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> ώρες</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">Αναπαραγωγή/παύση πολυμέσων</translation> <translation id="2148716181193084225">Σήμερα</translation> <translation id="7960078400008666149">Μην ενοχλείτε για μία ώρα</translation> <translation id="4373894838514502496">Πριν από <ph name="NUMBER_FEW"/> λεπτά</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Κύλιση δεξιά</translation> <translation id="7414887922320653780">Υπολείπεται <ph name="NUMBER_ONE"/> ώρα</translation> +<translation id="1413622004203049571">Απενεργοποίηση ειδοποιήσεων από <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Κορυφή</translation> <translation id="8331626408530291785">Κύλιση επάνω</translation> -<translation id="4773379706300191099">Απενεργοποίηση ειδοποιήσεων από <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Άνοιγμα Αρχείου</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045">Πριν από <ph name="NUMBER_DEFAULT"/> ώρες</translation> <translation id="815598010540052116">Κύλιση κάτω</translation> +<translation id="6808150112686056157">Διακοπή πολυμέσων</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Επαναφορά</translation> <translation id="1243314992276662751">Μεταφόρτωση</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497">Πριν από <ph name="NUMBER_MANY"/> λεπτά</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Βοήθεια</translation> +<translation id="6699343763173986273">Επόμενο κομμάτι πολυμέσων</translation> <translation id="8226233771743600312">Μην ενοχλείτε για μία ημέρα</translation> <translation id="7457942297256758195">Εκκαθάριση όλων</translation> <translation id="822618367988303761">Πριν από <ph name="NUMBER_TWO"/> ημέρες</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Ελαχιστοποίηση</translation> <translation id="6394627529324717982">Κόμμα</translation> -<translation id="4469842253116033348">Απενεργοποίηση ειδοποιήσεων από τον ιστότοπο <ph name="SITE"/></translation> <translation id="3036649622769666520">Άνοιγμα Αρχείων</translation> <translation id="8328145009876646418">Αριστερή άκρη</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> δευτερόλεπτα</translation> diff --git a/chromium/ui/base/strings/ui_strings_en-GB.xtb b/chromium/ui/base/strings/ui_strings_en-GB.xtb index fbe4dbd26d6..c620e94f938 100644 --- a/chromium/ui/base/strings/ui_strings_en-GB.xtb +++ b/chromium/ui/base/strings/ui_strings_en-GB.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Notification Centre</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> minutes left</translation> <translation id="5613020302032141669">Left Arrow</translation> +<translation id="4971687151119236543">Media Previous Track</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> File (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> secs</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> hours</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">Media Play/Pause</translation> <translation id="2148716181193084225">Today</translation> <translation id="7960078400008666149">Do not disturb for one hour</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> mins ago</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Scroll Right</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> hour left</translation> +<translation id="1413622004203049571">Disable notifications from <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Top</translation> <translation id="8331626408530291785">Scroll Up</translation> -<translation id="4773379706300191099">Disable notifications from <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Open File</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> hours ago</translation> <translation id="815598010540052116">Scroll Down</translation> +<translation id="6808150112686056157">Media Stop</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Restore</translation> <translation id="1243314992276662751">Upload</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Help</translation> +<translation id="6699343763173986273">Media Next Track</translation> <translation id="8226233771743600312">Do not disturb for one day</translation> <translation id="7457942297256758195">Clear All</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Minimise</translation> <translation id="6394627529324717982">Comma</translation> -<translation id="4469842253116033348">Disable notifications from <ph name="SITE"/></translation> <translation id="3036649622769666520">Open Files</translation> <translation id="8328145009876646418">Left Edge</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> seconds</translation> diff --git a/chromium/ui/base/strings/ui_strings_es-419.xtb b/chromium/ui/base/strings/ui_strings_es-419.xtb index 8ad1a3de438..d585d2676e8 100644 --- a/chromium/ui/base/strings/ui_strings_es-419.xtb +++ b/chromium/ui/base/strings/ui_strings_es-419.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Centro de notificaciones</translation> <translation id="7470933019269157899">Faltan <ph name="NUMBER_DEFAULT"/> minutos.</translation> <translation id="5613020302032141669">Flecha izquierda</translation> +<translation id="4971687151119236543">Pista multimedia anterior</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> Archivo (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> seg.</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> horas</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">Reproducir o pausar contenido multimedia</translation> <translation id="2148716181193084225">Hoy</translation> <translation id="7960078400008666149">No molestar durante una hora</translation> <translation id="4373894838514502496">Hace <ph name="NUMBER_FEW"/> minutos</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">RePág</translation> <translation id="4588090240171750605">Desplazar a la derecha</translation> <translation id="7414887922320653780">Falta <ph name="NUMBER_ONE"/> hora</translation> +<translation id="1413622004203049571">Inhabilitar notificaciones de <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Superior</translation> <translation id="8331626408530291785">Desplazar hacia arriba</translation> -<translation id="4773379706300191099">Inhabilitar las notificaciones de <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Abrir archivo</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045">Hace <ph name="NUMBER_DEFAULT"/> horas</translation> <translation id="815598010540052116">Desplazar hacia abajo</translation> +<translation id="6808150112686056157">Detener contenido multimedia</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Restaurar</translation> <translation id="1243314992276662751">Cargar</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497">Hace <ph name="NUMBER_MANY"/> minutos</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Ayuda</translation> +<translation id="6699343763173986273">Pista multimedia siguiente</translation> <translation id="8226233771743600312">No molestar durante un día</translation> <translation id="7457942297256758195">Borrar todo</translation> <translation id="822618367988303761">Hace <ph name="NUMBER_TWO"/> días</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Minimizar</translation> <translation id="6394627529324717982">Coma</translation> -<translation id="4469842253116033348">Inhabilitar las notificaciones desde <ph name="SITE"/></translation> <translation id="3036649622769666520">Abrir archivos</translation> <translation id="8328145009876646418">Borde izquierdo</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> seconds</translation> diff --git a/chromium/ui/base/strings/ui_strings_es.xtb b/chromium/ui/base/strings/ui_strings_es.xtb index 5394cc732bc..3e631195762 100644 --- a/chromium/ui/base/strings/ui_strings_es.xtb +++ b/chromium/ui/base/strings/ui_strings_es.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Centro de notificaciones</translation> <translation id="7470933019269157899">Quedan <ph name="NUMBER_DEFAULT"/> minutos</translation> <translation id="5613020302032141669">Flecha izquierda</translation> +<translation id="4971687151119236543">Pista anterior multimedia</translation> <translation id="8602707065186045623">Archivo <ph name="SAVEAS_EXTENSION_TYPE"/> (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> seg.</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> horas</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">Pausar/Reproducir contenido multimedia</translation> <translation id="2148716181193084225">Hoy</translation> <translation id="7960078400008666149">No molestar durante una hora</translation> <translation id="4373894838514502496">hace <ph name="NUMBER_FEW"/> minutos</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">RePág</translation> <translation id="4588090240171750605">Desplazar a la derecha</translation> <translation id="7414887922320653780">Falta <ph name="NUMBER_ONE"/> hora</translation> +<translation id="1413622004203049571">Inhabilitar notificaciones de <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Superior</translation> <translation id="8331626408530291785">Desplazar hacia arriba</translation> -<translation id="4773379706300191099">Inhabilitar notificaciones de <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Abrir archivo</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045">hace <ph name="NUMBER_DEFAULT"/> horas</translation> <translation id="815598010540052116">Desplazar hacia abajo</translation> +<translation id="6808150112686056157">Detener contenido multimedia</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Restaurar</translation> <translation id="1243314992276662751">Subir</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497">hace <ph name="NUMBER_MANY"/> minutos</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Ayuda</translation> +<translation id="6699343763173986273">Siguiente pista multimedia</translation> <translation id="8226233771743600312">No molestar durante un día</translation> <translation id="7457942297256758195">Borrar todo</translation> <translation id="822618367988303761">hace <ph name="NUMBER_TWO"/> días</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Minimizar</translation> <translation id="6394627529324717982">Coma</translation> -<translation id="4469842253116033348">Inhabilitar notificaciones de <ph name="SITE"/></translation> <translation id="3036649622769666520">Abrir archivos</translation> <translation id="8328145009876646418">Borde izquierdo</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> segundos</translation> diff --git a/chromium/ui/base/strings/ui_strings_et.xtb b/chromium/ui/base/strings/ui_strings_et.xtb index d5d9b6b63ab..3934ea29a88 100644 --- a/chromium/ui/base/strings/ui_strings_et.xtb +++ b/chromium/ui/base/strings/ui_strings_et.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Märguannete keskus</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> minutit on jäänud</translation> <translation id="5613020302032141669">Vasaknool</translation> +<translation id="4971687151119236543">Meediumi eelmine lugu</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> Fail (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> sekundit</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> tundi</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> kB/s</translation> +<translation id="8394908167088220973">Meediumi esitamine/peatamine</translation> <translation id="2148716181193084225">Täna</translation> <translation id="7960078400008666149">Mitte segada üks tund</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> minutit tagasi</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Keri paremale</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> tundi jäänud</translation> +<translation id="1413622004203049571">Keela märguanded: <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Üles</translation> <translation id="8331626408530291785">Keri üles</translation> -<translation id="4773379706300191099">Keela märguanded laiendusest <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Faili avamine</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> tundi tagasi</translation> <translation id="815598010540052116">Keri alla</translation> +<translation id="6808150112686056157">Meediumi peatamine</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Taasta</translation> <translation id="1243314992276662751">Laadi üles</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> minutit tagasi</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Abi</translation> +<translation id="6699343763173986273">Meediumi järgmine lugu</translation> <translation id="8226233771743600312">Mitte segada üks päev</translation> <translation id="7457942297256758195">Kustuta kõik</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> päeva tagasi</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Minimeeri</translation> <translation id="6394627529324717982">Koma</translation> -<translation id="4469842253116033348">Keela teated saidilt <ph name="SITE"/></translation> <translation id="3036649622769666520">Failide avamine</translation> <translation id="8328145009876646418">Vasak serv</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> seconds</translation> diff --git a/chromium/ui/base/strings/ui_strings_fa.xtb b/chromium/ui/base/strings/ui_strings_fa.xtb index 2cb91114128..62e36aae2af 100644 --- a/chromium/ui/base/strings/ui_strings_fa.xtb +++ b/chromium/ui/base/strings/ui_strings_fa.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">مرکز اعلان</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> دقیقه باقیمانده</translation> <translation id="5613020302032141669">پیکان چپ</translation> +<translation id="4971687151119236543">آهنگ قبلی رسانه</translation> <translation id="8602707065186045623">فایل <ph name="SAVEAS_EXTENSION_TYPE"/> (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> secs</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> hours</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> کیلوبایت/ثانیه</translation> +<translation id="8394908167088220973">پخش/توقف موقت رسانه</translation> <translation id="2148716181193084225">امروز</translation> <translation id="7960078400008666149">یک ساعت مزاحم نشوید</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> mins ago</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">پیمایش به راست</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> ساعت مانده</translation> +<translation id="1413622004203049571">غیرفعال کردن اعلانها از <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">بالا</translation> <translation id="8331626408530291785">پیمایش به بالا</translation> -<translation id="4773379706300191099">از کار انداختن اعلانهای <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">باز کردن فایل</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> ساعت قبل</translation> <translation id="815598010540052116">پیمایش به پایین</translation> +<translation id="6808150112686056157">توقف رسانه</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">بازیابی</translation> <translation id="1243314992276662751">آپلود</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> بایت/ثانیه</translation> <translation id="7649070708921625228">راهنما</translation> +<translation id="6699343763173986273">آهنگ بعدی رسانه</translation> <translation id="8226233771743600312">یک روز مزاحم نشوید</translation> <translation id="7457942297256758195">پاک کردن همه</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">کوچک کردن</translation> <translation id="6394627529324717982">کاما</translation> -<translation id="4469842253116033348">غیر فعال کردن اعلام های <ph name="SITE"/></translation> <translation id="3036649622769666520">باز کردن فایلها</translation> <translation id="8328145009876646418">حاشیه چپ</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> ثانیه</translation> diff --git a/chromium/ui/base/strings/ui_strings_fi.xtb b/chromium/ui/base/strings/ui_strings_fi.xtb index a6b04bf63eb..73eae4fd3b1 100644 --- a/chromium/ui/base/strings/ui_strings_fi.xtb +++ b/chromium/ui/base/strings/ui_strings_fi.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Ilmoituskeskus</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> minuuttia jäljellä</translation> <translation id="5613020302032141669">Nuoli vas.</translation> +<translation id="4971687151119236543">Media: edellinen kappale</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/>-tiedosto (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> sekuntia</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> tuntia</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> kt/s</translation> +<translation id="8394908167088220973">Media: toista/keskeytä</translation> <translation id="2148716181193084225">Tänään</translation> <translation id="7960078400008666149">Älä häiritse tuntiin</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> mins ago</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Vieritä oikealle</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> tuntia jäljellä</translation> +<translation id="1413622004203049571">Poista ilmoitukset käytöstä sovellukselta <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Yleisin</translation> <translation id="8331626408530291785">Vieritä ylös</translation> -<translation id="4773379706300191099">Poista ilmoitukset käytöstä laajennukselta <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Avaa tiedosto</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> tuntia sitten</translation> <translation id="815598010540052116">Vieritä alas</translation> +<translation id="6808150112686056157">Media: pysäytä</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Palauta</translation> <translation id="1243314992276662751">Lähetä</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> t/s</translation> <translation id="7649070708921625228">Ohje</translation> +<translation id="6699343763173986273">Media: seuraava kappale</translation> <translation id="8226233771743600312">Älä häiritse päivään</translation> <translation id="7457942297256758195">Tyhjennä kaikki</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Pienennä</translation> <translation id="6394627529324717982">Pilkku</translation> -<translation id="4469842253116033348">Poista sivuston <ph name="SITE"/> ilmoitukset käytöstä</translation> <translation id="3036649622769666520">Avaa tiedostot</translation> <translation id="8328145009876646418">Vasen reuna</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> seconds</translation> diff --git a/chromium/ui/base/strings/ui_strings_fil.xtb b/chromium/ui/base/strings/ui_strings_fil.xtb index 5ef326400c3..31dbaeca296 100644 --- a/chromium/ui/base/strings/ui_strings_fil.xtb +++ b/chromium/ui/base/strings/ui_strings_fil.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Notification Center</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> (na) minuto ang natitira</translation> <translation id="5613020302032141669">KAliwang Arrow</translation> +<translation id="4971687151119236543">Nakaraang Track ng Media</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> File (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> segundo</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> mga oras</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">I-Play/I-Pause ang Media</translation> <translation id="2148716181193084225">Ngayon</translation> <translation id="7960078400008666149">Huwag istorbohin sa loob ng isang oras</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> minuto ang nakalipas</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Mag-scroll Pakanan</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> natitirang oras</translation> +<translation id="1413622004203049571">I-disable ang mga notification mula sa <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Tuktok</translation> <translation id="8331626408530291785">Mag-scroll Pataas</translation> -<translation id="4773379706300191099">I-disable ang mga notification mula sa <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Buksan ang File</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> na oras ang nakalipas</translation> <translation id="815598010540052116">Mag-scroll Pababa</translation> +<translation id="6808150112686056157">Media Ihinto</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Ipanumbalik</translation> <translation id="1243314992276662751">I-upload</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> minuto ang nakalipas</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> (na) B/s</translation> <translation id="7649070708921625228">Tulong</translation> +<translation id="6699343763173986273">Susunod na Track ng Media</translation> <translation id="8226233771743600312">Huwag istorbohin sa loob ng isang araw</translation> <translation id="7457942297256758195">I-clear Lahat</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> araw ang nakalipas</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Minimize</translation> <translation id="6394627529324717982">Kuwit</translation> -<translation id="4469842253116033348">Huwag paganahin ang mga abiso mula sa <ph name="SITE"/></translation> <translation id="3036649622769666520">Buksan ang Mga File</translation> <translation id="8328145009876646418">Kalwang Edge</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> segundo</translation> diff --git a/chromium/ui/base/strings/ui_strings_fr.xtb b/chromium/ui/base/strings/ui_strings_fr.xtb index d6d48faca18..7c6cc69c636 100644 --- a/chromium/ui/base/strings/ui_strings_fr.xtb +++ b/chromium/ui/base/strings/ui_strings_fr.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Centre de notification</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> minutes restantes</translation> <translation id="5613020302032141669">Gauche</translation> +<translation id="4971687151119236543">Contenu multimédia : titre précédent</translation> <translation id="8602707065186045623">Fichier <ph name="SAVEAS_EXTENSION_TYPE"/> (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> secondes</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> heures</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> Ko/s</translation> +<translation id="8394908167088220973">Contenu multimédia : lecture/pause</translation> <translation id="2148716181193084225">Aujourd'hui</translation> <translation id="7960078400008666149">Ne pas déranger pendant une heure</translation> <translation id="4373894838514502496">il y a <ph name="NUMBER_FEW"/> minutes</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgPréc</translation> <translation id="4588090240171750605">Défilement vers la droite</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> heure restante</translation> +<translation id="1413622004203049571">Désactiver les notifications <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">En haut</translation> <translation id="8331626408530291785">Défilement vers le haut</translation> -<translation id="4773379706300191099">Désactiver les notifications de l'extension "<ph name="EXTENSION_NAME"/>"</translation> <translation id="7907591526440419938">Ouvrir le fichier</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Échap</translation> <translation id="2797524280730715045">il y a <ph name="NUMBER_DEFAULT"/> heures</translation> <translation id="815598010540052116">Défilement vers le bas</translation> +<translation id="6808150112686056157">Contenu multimédia : arrêt</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Restaurer</translation> <translation id="1243314992276662751">Importer</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> o/s</translation> <translation id="7649070708921625228">Aide</translation> +<translation id="6699343763173986273">Contenu multimédia : titre suivant</translation> <translation id="8226233771743600312">Ne pas déranger pendant un jour</translation> <translation id="7457942297256758195">Tout effacer</translation> <translation id="822618367988303761">il y a <ph name="NUMBER_TWO"/> jours</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Réduire</translation> <translation id="6394627529324717982">Virgule</translation> -<translation id="4469842253116033348">Désactiver les notifications de <ph name="SITE"/></translation> <translation id="3036649622769666520">Ouvrir les fichiers</translation> <translation id="8328145009876646418">Côté gauche</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> seconds</translation> diff --git a/chromium/ui/base/strings/ui_strings_gu.xtb b/chromium/ui/base/strings/ui_strings_gu.xtb index 0cf8377e178..5a24f98cc94 100644 --- a/chromium/ui/base/strings/ui_strings_gu.xtb +++ b/chromium/ui/base/strings/ui_strings_gu.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">સૂચના કેન્દ્ર</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> મિનિટ બાકી</translation> <translation id="5613020302032141669">ડાબો એરો</translation> +<translation id="4971687151119236543">મીડિયા પહેલાંનું ટ્રૅક</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> ફાઇલ (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> મિનિટ પહેલા</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> સેકંડ</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> કલાક</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">મીડિયા ચલાવો/થોભાવો</translation> <translation id="2148716181193084225">આજે</translation> <translation id="7960078400008666149">એક કલાક માટે ખલેલ પાડશો નહીં</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> mins ago</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">જમણે સ્ક્રોલ કરો</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> કલાક બાકી</translation> +<translation id="1413622004203049571"><ph name="NOTIFIER_NAME"/> તરફથી સૂચનાઓ અક્ષમ કરો</translation> <translation id="2666092431469916601">ઉપર</translation> <translation id="8331626408530291785">ઉપર સ્ક્રોલ કરો</translation> -<translation id="4773379706300191099"><ph name="EXTENSION_NAME"/> થી સૂચનાઓને અક્ષમ કરો</translation> <translation id="7907591526440419938">ફાઇલ ખોલો</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> દિવસ બાકી</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> hours ago</translation> <translation id="815598010540052116">નીચે સ્ક્રોલ કરો</translation> +<translation id="6808150112686056157">મીડિયા સ્ટોપ</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> મિનિટ બાકી</translation> <translation id="3157931365184549694">પુનઃસ્થાપિત કરો</translation> <translation id="1243314992276662751">અપલોડ કરો</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">સહાય</translation> +<translation id="6699343763173986273">મીડિયા આગલો ટ્રૅક</translation> <translation id="8226233771743600312">એક દિવસ માટે ખલેલ પાડશો નહીં</translation> <translation id="7457942297256758195">બધું સાફ કરો</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> દિવસ પહેલા</translation> <translation id="5941711191222866238">નાનું કરો</translation> <translation id="6394627529324717982">અલ્પવિરામ</translation> -<translation id="4469842253116033348"><ph name="SITE"/> તરફની સૂચનાઓ અક્ષમ કરો </translation> <translation id="3036649622769666520">ફાઇલો ખોલો</translation> <translation id="8328145009876646418">ડાબી કિનારી</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> સેકંડ</translation> diff --git a/chromium/ui/base/strings/ui_strings_hi.xtb b/chromium/ui/base/strings/ui_strings_hi.xtb index 3b842bc2126..6d03ce17e67 100644 --- a/chromium/ui/base/strings/ui_strings_hi.xtb +++ b/chromium/ui/base/strings/ui_strings_hi.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">सूचना केंद्र</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> मिनट शेष</translation> <translation id="5613020302032141669">बायां तीर</translation> +<translation id="4971687151119236543">मीडिया पिछला ट्रैक</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> फ़ाइल (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> सेकंड</translation> @@ -105,6 +106,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> घंटे</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">मीडिया चलाएं/रोकें</translation> <translation id="2148716181193084225">आज</translation> <translation id="7960078400008666149">एक घंटे तक परेशान न करें</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> mins ago</translation> @@ -115,20 +117,21 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">दाएं स्क्रॉल करें</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> घंटे शेष</translation> +<translation id="1413622004203049571"><ph name="NOTIFIER_NAME"/> से सूचनाएं अक्षम करें</translation> <translation id="2666092431469916601">शीर्ष</translation> <translation id="8331626408530291785">ऊपर स्क्रॉल करें</translation> -<translation id="4773379706300191099"><ph name="EXTENSION_NAME"/> की सूचनाएं अक्षम करें</translation> <translation id="7907591526440419938">फ़ाइल खोलें</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> घंटे पहले</translation> <translation id="815598010540052116">नीचे स्क्रॉल करें</translation> +<translation id="6808150112686056157">मीडिया रोकें</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">पुनर्स्थापित करें</translation> <translation id="1243314992276662751">अपलोड करें</translation> <translation id="50030952220075532"><ph name="NUMBER_ONE"/> दिन शेष</translation> <translation id="8179976553408161302">प्रविष्ट करें</translation> -<translation id="945522503751344254">फ़ीडबैक भेजें</translation> +<translation id="945522503751344254">सुझाव भेजें</translation> <translation id="9170848237812810038">&पूर्ववत् करें</translation> <translation id="1285266685456062655"><ph name="NUMBER_FEW"/> घंटे पहले</translation> <translation id="6918245111648057970">प्रत्येक उपयोगकर्ता के लिए निम्न में से सूचनाओं की अनुमति दें:</translation> @@ -161,6 +164,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">सहायता</translation> +<translation id="6699343763173986273">मीडिया अगला ट्रैक</translation> <translation id="8226233771743600312">एक दिन तक परेशान न करें</translation> <translation id="7457942297256758195">सभी साफ़ करें</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> दिन पहले</translation> @@ -180,7 +184,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> दिन पहले</translation> <translation id="5941711191222866238">छोटा करें</translation> <translation id="6394627529324717982">अल्पविराम</translation> -<translation id="4469842253116033348"><ph name="SITE"/> से सूचनाएं अक्षम करें</translation> <translation id="3036649622769666520">फ़ाइलें खोलें</translation> <translation id="8328145009876646418">बायां सिरा</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> सेकंड</translation> diff --git a/chromium/ui/base/strings/ui_strings_hr.xtb b/chromium/ui/base/strings/ui_strings_hr.xtb index a10b9321851..aa88cb0fdfc 100644 --- a/chromium/ui/base/strings/ui_strings_hr.xtb +++ b/chromium/ui/base/strings/ui_strings_hr.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Centar za obavijesti</translation> <translation id="7470933019269157899">Preostalo minuta: <ph name="NUMBER_DEFAULT"/></translation> <translation id="5613020302032141669">Strelica lijevo</translation> +<translation id="4971687151119236543">Prethodni zapis Medija</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> Datoteka (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252">Broj sekundi: <ph name="NUMBER_TWO"/></translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401">Sati: <ph name="NUMBER_MANY"/></translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">Reproduciraj/pauziraj Medije</translation> <translation id="2148716181193084225">Danas</translation> <translation id="7960078400008666149">Ne ometaj jedan sat</translation> <translation id="4373894838514502496">Prije <ph name="NUMBER_FEW"/> min</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Pomakni se desno</translation> <translation id="7414887922320653780">Preostalo sati: <ph name="NUMBER_ONE"/></translation> +<translation id="1413622004203049571">Onemogući obavijesti pošiljatelja <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Gornji</translation> <translation id="8331626408530291785">Pomakni se gore</translation> -<translation id="4773379706300191099">Onemogućivanje obavijesti proširenja <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Otvori datoteku</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045">Prije <ph name="NUMBER_DEFAULT"/> sati</translation> <translation id="815598010540052116">Pomakni se dolje</translation> +<translation id="6808150112686056157">Zaustavi Medije</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Vrati</translation> <translation id="1243314992276662751">Prenesi</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Pomoć</translation> +<translation id="6699343763173986273">Sljedeći zapis Medija</translation> <translation id="8226233771743600312">Ne ometaj jedan dan</translation> <translation id="7457942297256758195">Očisti sve</translation> <translation id="822618367988303761">Prije <ph name="NUMBER_TWO"/> dana</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Minimiziraj</translation> <translation id="6394627529324717982">Zarez</translation> -<translation id="4469842253116033348">Onemogući obavijesti s web-lokacije <ph name="SITE"/></translation> <translation id="3036649622769666520">Otvori datoteke</translation> <translation id="8328145009876646418">Lijevi rub</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> seconds</translation> diff --git a/chromium/ui/base/strings/ui_strings_hu.xtb b/chromium/ui/base/strings/ui_strings_hu.xtb index 8266d2cede9..c48a91b34dc 100644 --- a/chromium/ui/base/strings/ui_strings_hu.xtb +++ b/chromium/ui/base/strings/ui_strings_hu.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Értesítési központ</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> perc van hátra</translation> <translation id="5613020302032141669">Bal nyíl</translation> +<translation id="4971687151119236543">Előző szám</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> fájl (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> másodperc</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> óra</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> kB/s</translation> +<translation id="8394908167088220973">Lejátszás/szüneteltetés</translation> <translation id="2148716181193084225">Ma</translation> <translation id="7960078400008666149">Ne zavarj egy óráig</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> mins ago</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Görgetés jobbra</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> óra van hátra</translation> +<translation id="1413622004203049571">A(z) <ph name="NOTIFIER_NAME"/> értesítéseinek kikapcsolása</translation> <translation id="2666092431469916601">Felülre</translation> <translation id="8331626408530291785">Görgetés felfelé</translation> -<translation id="4773379706300191099"><ph name="EXTENSION_NAME"/> értesítéseinek kikapcsolása</translation> <translation id="7907591526440419938">Fájl megnyitása</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> órája</translation> <translation id="815598010540052116">Görgetés lefelé</translation> +<translation id="6808150112686056157">Leállítás</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Visszaállítás</translation> <translation id="1243314992276662751">Feltöltés</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Súgó</translation> +<translation id="6699343763173986273">Következő szám</translation> <translation id="8226233771743600312">Ne zavarj egy napig</translation> <translation id="7457942297256758195">Összes törlése</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Kicsinyítés</translation> <translation id="6394627529324717982">Vessző</translation> -<translation id="4469842253116033348"><ph name="SITE"/> értesítéseinek kikapcsolása</translation> <translation id="3036649622769666520">Fájlok megnyitása</translation> <translation id="8328145009876646418">Bal sarok</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> másodperc</translation> diff --git a/chromium/ui/base/strings/ui_strings_id.xtb b/chromium/ui/base/strings/ui_strings_id.xtb index 3175df4f9eb..747a5c8d8d0 100644 --- a/chromium/ui/base/strings/ui_strings_id.xtb +++ b/chromium/ui/base/strings/ui_strings_id.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Pusat Pemberitahuan</translation> <translation id="7470933019269157899">Tersisa <ph name="NUMBER_DEFAULT"/> menit</translation> <translation id="5613020302032141669">Panah Kiri</translation> +<translation id="4971687151119236543">Lacak Media Sebelumnya</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> File (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> detik</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> jam</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/dtk</translation> +<translation id="8394908167088220973">Putar/Jeda Media</translation> <translation id="2148716181193084225">Hari ini</translation> <translation id="7960078400008666149">Jangan ganggu selama satu jam</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> mnt. yang lalu</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Gulir ke Kanan</translation> <translation id="7414887922320653780">Tersisa <ph name="NUMBER_ONE"/> jam</translation> +<translation id="1413622004203049571">Nonaktifkan pemberitahuan dari <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Atas</translation> <translation id="8331626408530291785">Gulir ke Atas</translation> -<translation id="4773379706300191099">Nonaktifkan pemberitahuan dari <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Buka File</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> jam yang lalu</translation> <translation id="815598010540052116">Gulir ke Bawah</translation> +<translation id="6808150112686056157">Hentikan Media</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Pulihkan</translation> <translation id="1243314992276662751">Unggah</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mnt. yang lalu</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/dtk</translation> <translation id="7649070708921625228">Bantuan</translation> +<translation id="6699343763173986273">Lacak Media Berikutnya</translation> <translation id="8226233771743600312">Jangan ganggu selama satu hari</translation> <translation id="7457942297256758195">Hapus Semua</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> hari yang lalu</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Perkecil</translation> <translation id="6394627529324717982">Koma</translation> -<translation id="4469842253116033348">Nonaktifkan pemberitahuan dari <ph name="SITE"/></translation> <translation id="3036649622769666520">Buka File</translation> <translation id="8328145009876646418">Tepi Kiri</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> detik</translation> diff --git a/chromium/ui/base/strings/ui_strings_it.xtb b/chromium/ui/base/strings/ui_strings_it.xtb index 003abcf6928..3df1779e5c3 100644 --- a/chromium/ui/base/strings/ui_strings_it.xtb +++ b/chromium/ui/base/strings/ui_strings_it.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Centro notifiche</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> minuti rimanenti</translation> <translation id="5613020302032141669">Freccia sinistra</translation> +<translation id="4971687151119236543">Traccia precedente contenuti multimediali</translation> <translation id="8602707065186045623">File <ph name="SAVEAS_EXTENSION_TYPE"/> (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> sec.</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> ore</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> kB/s</translation> +<translation id="8394908167088220973">Play/Pausa contenuti multimediali</translation> <translation id="2148716181193084225">Oggi</translation> <translation id="7960078400008666149">Non disturbare per un'ora</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> minuti fa</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PGSU</translation> <translation id="4588090240171750605">Scorri a destra</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> ora rimanente</translation> +<translation id="1413622004203049571">Disabilita notifiche da <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">In alto</translation> <translation id="8331626408530291785">Scorri verso l'alto</translation> -<translation id="4773379706300191099">Disattiva notifiche da <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Apri file</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> ore fa</translation> <translation id="815598010540052116">Scorri verso il basso</translation> +<translation id="6808150112686056157">Interrompi contenuti multimediali</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Ripristina</translation> <translation id="1243314992276662751">Carica</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> minuti fa</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Guida</translation> +<translation id="6699343763173986273">Traccia successiva contenuti multimediali</translation> <translation id="8226233771743600312">Non disturbare per un giorno</translation> <translation id="7457942297256758195">Cancella tutto</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> giorni fa</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Riduci a icona</translation> <translation id="6394627529324717982">Virgola</translation> -<translation id="4469842253116033348">Disabilita notifiche da <ph name="SITE"/></translation> <translation id="3036649622769666520">Apri file</translation> <translation id="8328145009876646418">Margine sinistro</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> seconds</translation> diff --git a/chromium/ui/base/strings/ui_strings_iw.xtb b/chromium/ui/base/strings/ui_strings_iw.xtb index 80040340423..7f640838a2b 100644 --- a/chromium/ui/base/strings/ui_strings_iw.xtb +++ b/chromium/ui/base/strings/ui_strings_iw.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">מרכז התראות</translation> <translation id="7470933019269157899">נותרו <ph name="NUMBER_DEFAULT"/> דקות</translation> <translation id="5613020302032141669">חץ לשמאל</translation> +<translation id="4971687151119236543">רצועה קודמת במדיה</translation> <translation id="8602707065186045623">קובץ <ph name="SAVEAS_EXTENSION_TYPE"/> (<ph name="SAVEAS_EXTENSION_NAME"/>.)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> שניות</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> שעות</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">הפעלה/השהיה של המדיה</translation> <translation id="2148716181193084225">היום</translation> <translation id="7960078400008666149">נא לא להפריע למשך שעה</translation> <translation id="4373894838514502496">לפני <ph name="NUMBER_FEW"/> דקות</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">גלול ימינה</translation> <translation id="7414887922320653780">נותרו <ph name="NUMBER_ONE"/> שעות</translation> +<translation id="1413622004203049571">השבת הודעות מאת <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">למעלה</translation> <translation id="8331626408530291785">גלול למעלה</translation> -<translation id="4773379706300191099">השבת התראות מהתוסף <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">פתח קובץ</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045">לפני <ph name="NUMBER_DEFAULT"/> שעות</translation> <translation id="815598010540052116">גלול למטה</translation> +<translation id="6808150112686056157">עצור מדיה</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">שחזר</translation> <translation id="1243314992276662751">העלה</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497">לפני <ph name="NUMBER_MANY"/> דקות</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">עזרה</translation> +<translation id="6699343763173986273">הרצועה הבאה במדיה</translation> <translation id="8226233771743600312">נא לא להפריע ליום אחד</translation> <translation id="7457942297256758195">נקה הכל</translation> <translation id="822618367988303761">לפני <ph name="NUMBER_TWO"/> ימים</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">מזער</translation> <translation id="6394627529324717982">פסיק</translation> -<translation id="4469842253116033348">השבת הודעות מ-<ph name="SITE"/></translation> <translation id="3036649622769666520">פתח קבצים</translation> <translation id="8328145009876646418">קצה שמאלי</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> שניות</translation> diff --git a/chromium/ui/base/strings/ui_strings_ja.xtb b/chromium/ui/base/strings/ui_strings_ja.xtb index 06b3c8cb05d..5dc08123b1d 100644 --- a/chromium/ui/base/strings/ui_strings_ja.xtb +++ b/chromium/ui/base/strings/ui_strings_ja.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">通知センター</translation> <translation id="7470933019269157899">残り <ph name="NUMBER_DEFAULT"/> 分</translation> <translation id="5613020302032141669">左矢印キー</translation> +<translation id="4971687151119236543">メディアの前のトラック</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> ファイル (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> 秒</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> 時間</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/秒</translation> +<translation id="8394908167088220973">メディアの再生/一時停止</translation> <translation id="2148716181193084225">今日</translation> <translation id="7960078400008666149">通知を 1 時間ミュート</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> 分前</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PageUp</translation> <translation id="4588090240171750605">右にスクロール</translation> <translation id="7414887922320653780">残り <ph name="NUMBER_ONE"/> 時間</translation> +<translation id="1413622004203049571"><ph name="NOTIFIER_NAME"/> からの通知を無効にする</translation> <translation id="2666092431469916601">一番上</translation> <translation id="8331626408530291785">上にスクロール</translation> -<translation id="4773379706300191099"><ph name="EXTENSION_NAME"/> の通知を無効にする</translation> <translation id="7907591526440419938">ファイルを開く</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> 時間前</translation> <translation id="815598010540052116">下にスクロール</translation> +<translation id="6808150112686056157">メディアの停止</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">復元</translation> <translation id="1243314992276662751">アップロード</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> 分前</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/秒</translation> <translation id="7649070708921625228">ヘルプ</translation> +<translation id="6699343763173986273">メディアの次のトラック</translation> <translation id="8226233771743600312">通知を 1 日間ミュート</translation> <translation id="7457942297256758195">すべて消去</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> 日前</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">最小化</translation> <translation id="6394627529324717982">カンマ</translation> -<translation id="4469842253116033348"><ph name="SITE"/> からの通知を無効にする</translation> <translation id="3036649622769666520">ファイルを開く</translation> <translation id="8328145009876646418">左端</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> 秒</translation> diff --git a/chromium/ui/base/strings/ui_strings_kn.xtb b/chromium/ui/base/strings/ui_strings_kn.xtb index a5cc7982f4c..421ecec6388 100644 --- a/chromium/ui/base/strings/ui_strings_kn.xtb +++ b/chromium/ui/base/strings/ui_strings_kn.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">ಅಧಿಸೂಚನೆಯ ಕೇಂದ್ರ</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> ನಿಮಿಷಗಳು ಉಳಿದಿವೆ</translation> <translation id="5613020302032141669">ಎಡ ಬಾಣದ ಗುರುತು</translation> +<translation id="4971687151119236543">ಮೀಡಿಯಾದ ಹಿಂದಿನ ಟ್ರ್ಯಾಕ್</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> ಫೈಲ್ (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> ಸೆಕೆಂಡುಗಳು</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> ಗಂಟೆಗಳು</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s </translation> +<translation id="8394908167088220973">ಮೀಡಿಯಾ ಪ್ಲೇ/ವಿರಾಮ</translation> <translation id="2148716181193084225">ಇಂದು</translation> <translation id="7960078400008666149">ಒಂದು ಗಂಟೆಯ ಕಾಲ ಅಡಚಣೆ ಮಾಡಬೇಡಿ</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> mins ago</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">ಬಲಕ್ಕೆ ಸ್ಕ್ರೋಲ್ ಮಾಡಿ</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> ಗಂಟೆಗಳು ಉಳಿದಿದೆ</translation> +<translation id="1413622004203049571"><ph name="NOTIFIER_NAME"/> ಅವರ ಅಧಿಸೂಚನೆಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ</translation> <translation id="2666092431469916601">ಮೇಲೆ</translation> <translation id="8331626408530291785">ಮೇಲೆ ಸ್ಕ್ರೋಲ್ ಮಾಡು</translation> -<translation id="4773379706300191099"><ph name="EXTENSION_NAME"/> ನಿಂದ ಅಧಿಸೂಚನೆಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ</translation> <translation id="7907591526440419938">ಫೈಲ್ ತೆರೆಯಿರಿ</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> hours ago</translation> <translation id="815598010540052116">ಕೆಳಗೆ ಸ್ಕ್ರೋಲ್ ಮಾಡು</translation> +<translation id="6808150112686056157">ಮೀಡಿಯಾ ನಿಲುಗಡೆ</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">ಪುನಃಸ್ಥಾಪನೆ</translation> <translation id="1243314992276662751">ಅಪ್ಲೋಡ್</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">ಸಹಾಯ</translation> +<translation id="6699343763173986273">ಮೀಡಿಯಾದ ಮುಂದಿನ ಟ್ರ್ಯಾಕ್</translation> <translation id="8226233771743600312">ಒಂದು ದಿನದವರೆಗೆ ಅಡಚಣೆ ಮಾಡಬೇಡಿ</translation> <translation id="7457942297256758195">ಎಲ್ಲವನ್ನೂ ತೆರವುಗೊಳಿಸಿ</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">ಕುಗ್ಗಿಸು</translation> <translation id="6394627529324717982">ಅರ್ಧವಿರಾಮ</translation> -<translation id="4469842253116033348"><ph name="SITE"/> ನಿಂದ ಪ್ರಕಟಣೆಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ</translation> <translation id="3036649622769666520">ಫೈಲ್ಗಳನ್ನು ತೆರೆಯಿರಿ</translation> <translation id="8328145009876646418">ಎಡ ಬದಿ</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> ಸೆಕೆಂಡುಗಳು</translation> diff --git a/chromium/ui/base/strings/ui_strings_ko.xtb b/chromium/ui/base/strings/ui_strings_ko.xtb index 2403ee083e9..3794c67ca3b 100644 --- a/chromium/ui/base/strings/ui_strings_ko.xtb +++ b/chromium/ui/base/strings/ui_strings_ko.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">알림 센터</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/>분 남음</translation> <translation id="5613020302032141669">왼쪽 화살표</translation> +<translation id="4971687151119236543">미디어 이전 트랙</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> 파일(.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/>초</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/>시간</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/>KB/초</translation> +<translation id="8394908167088220973">미디어 재생/일시중지</translation> <translation id="2148716181193084225">오늘</translation> <translation id="7960078400008666149">1시간 동안 알림 일시중지</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/>분 전</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PageUp</translation> <translation id="4588090240171750605">오른쪽 스크롤</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/>시간 남음</translation> +<translation id="1413622004203049571"><ph name="NOTIFIER_NAME"/>의 알림 사용 중지</translation> <translation id="2666092431469916601">맨 위</translation> <translation id="8331626408530291785">위로 스크롤</translation> -<translation id="4773379706300191099"><ph name="EXTENSION_NAME"/> 알림 사용 안함</translation> <translation id="7907591526440419938">파일 열기</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/>시간 전</translation> <translation id="815598010540052116">아래로 스크롤</translation> +<translation id="6808150112686056157">미디어 중지</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">복구</translation> <translation id="1243314992276662751">업로드</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/>분 전</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/>B/s</translation> <translation id="7649070708921625228">도움말</translation> +<translation id="6699343763173986273">미디어 다음 트랙</translation> <translation id="8226233771743600312">하루 동안 알림 일시중지</translation> <translation id="7457942297256758195">모두 지우기</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/>일 전</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">최소화</translation> <translation id="6394627529324717982">콤마</translation> -<translation id="4469842253116033348"><ph name="SITE"/>의 알림을 표시 안함</translation> <translation id="3036649622769666520">파일 열기</translation> <translation id="8328145009876646418">왼쪽 모서리</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/>초</translation> diff --git a/chromium/ui/base/strings/ui_strings_lt.xtb b/chromium/ui/base/strings/ui_strings_lt.xtb index afe0ced61dd..f36210e5675 100644 --- a/chromium/ui/base/strings/ui_strings_lt.xtb +++ b/chromium/ui/base/strings/ui_strings_lt.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Pranešimų centras</translation> <translation id="7470933019269157899">Liko <ph name="NUMBER_DEFAULT"/> min.</translation> <translation id="5613020302032141669">Rodyklė į kairę</translation> +<translation id="4971687151119236543">Ankstesnis medijos takelis</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> failas (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> sek.</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> valandos (-ų)</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB per sek.</translation> +<translation id="8394908167088220973">Leisti / pristabdyti mediją</translation> <translation id="2148716181193084225">Šiandien</translation> <translation id="7960078400008666149">Netrukdyti vieną valandą</translation> <translation id="4373894838514502496">Prieš <ph name="NUMBER_FEW"/> min.</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Slinkti į dešinę</translation> <translation id="7414887922320653780">liko <ph name="NUMBER_ONE"/> val.</translation> +<translation id="1413622004203049571">Išjungti pranešimus nuo <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Į viršų</translation> <translation id="8331626408530291785">Slinkti į viršų</translation> -<translation id="4773379706300191099">Neleisti „<ph name="EXTENSION_NAME"/>“ pranešimų.</translation> <translation id="7907591526440419938">Atidaryti failą</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045">Prieš <ph name="NUMBER_DEFAULT"/> val.</translation> <translation id="815598010540052116">Slinkti žemyn</translation> +<translation id="6808150112686056157">Sustabdyti mediją</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Atkurti</translation> <translation id="1243314992276662751">Įkelti</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497">Prieš <ph name="NUMBER_MANY"/> min.</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Žinynas</translation> +<translation id="6699343763173986273">Kitas medijos takelis</translation> <translation id="8226233771743600312">Netrukdyti vieną dieną</translation> <translation id="7457942297256758195">Išvalyti viską</translation> <translation id="822618367988303761">Prieš <ph name="NUMBER_TWO"/> dienas</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Sumažinti</translation> <translation id="6394627529324717982">Kablelis</translation> -<translation id="4469842253116033348">Neleisti <ph name="SITE"/> plėtinių</translation> <translation id="3036649622769666520">Atidaryti failus</translation> <translation id="8328145009876646418">Kairysis kraštas</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> sek.</translation> diff --git a/chromium/ui/base/strings/ui_strings_lv.xtb b/chromium/ui/base/strings/ui_strings_lv.xtb index 65622f1a695..6de184fa0fe 100644 --- a/chromium/ui/base/strings/ui_strings_lv.xtb +++ b/chromium/ui/base/strings/ui_strings_lv.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Paziņojumu centrs</translation> <translation id="7470933019269157899">Atlikušas <ph name="NUMBER_DEFAULT"/> minūtes</translation> <translation id="5613020302032141669">Kreisā bulta</translation> +<translation id="4971687151119236543">Multivide — iepriekšējā dziesma</translation> <translation id="8602707065186045623">Fails <ph name="SAVEAS_EXTENSION_TYPE"/> (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> sekundes</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">taustiņš F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> stundas</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">Multivide — atskaņot/apturēt</translation> <translation id="2148716181193084225">Šodien</translation> <translation id="7960078400008666149">Netraucēt stundu</translation> <translation id="4373894838514502496">Pirms <ph name="NUMBER_FEW"/> minūtēm</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">Augšup</translation> <translation id="4588090240171750605">Ritināt pa labi</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> stundas atlikušas</translation> +<translation id="1413622004203049571">Atspējot paziņojumu saņemšanu no: <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Augša</translation> <translation id="8331626408530291785">Ritināt augšup</translation> -<translation id="4773379706300191099">Atspējot paziņojumu saņemšanu no: <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Atvērt failu</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Atsolis</translation> <translation id="2797524280730715045">Pirms <ph name="NUMBER_DEFAULT"/> stundām</translation> <translation id="815598010540052116">Ritināt lejup</translation> +<translation id="6808150112686056157">Multivide — pārtraukt</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Atjaunot</translation> <translation id="1243314992276662751">Augšupielādēt</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Palīdzība</translation> +<translation id="6699343763173986273">Multivide — nākamā dziesma</translation> <translation id="8226233771743600312">Netraucēt dienu</translation> <translation id="7457942297256758195">Notīrīt visu</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Minimizēt</translation> <translation id="6394627529324717982">Komats</translation> -<translation id="4469842253116033348">Atspējot vietnes <ph name="SITE"/> paziņojumus</translation> <translation id="3036649622769666520">Atvērt failus</translation> <translation id="8328145009876646418">Kreisā mala</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> seconds</translation> diff --git a/chromium/ui/base/strings/ui_strings_ml.xtb b/chromium/ui/base/strings/ui_strings_ml.xtb index 13bb6e29370..a960d411b0b 100644 --- a/chromium/ui/base/strings/ui_strings_ml.xtb +++ b/chromium/ui/base/strings/ui_strings_ml.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">അറിയിപ്പ് കേന്ദ്രം</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> മിനിറ്റ് ശേഷിക്കുന്നു</translation> <translation id="5613020302032141669">ഇടത് ആരോ അടയാളം</translation> +<translation id="4971687151119236543">മുമ്പത്തെ മീഡിയ ട്രാക്ക്</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> ഫയല് (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> സെക്കന്റ്</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> മണിക്കൂര്</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">മീഡിയ പ്ലേ ചെയ്യുക/താൽക്കാലികമായി നിർത്തുക</translation> <translation id="2148716181193084225">ഇന്ന്</translation> <translation id="7960078400008666149">ഒരു മണിക്കൂർ നേരത്തേക്ക് ശല്യപ്പെടുത്തരുത്</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> mins ago</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">വലത്തോട്ട് സ്ക്രോള് ചെയ്യുക</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> മണിക്കൂര് ശേഷിക്കുന്നു</translation> +<translation id="1413622004203049571"><ph name="NOTIFIER_NAME"/> എന്നതിൽ നിന്നുള്ള അറിയിപ്പുകൾ പ്രവർത്തനരഹിതമാക്കുക</translation> <translation id="2666092431469916601">മുകളിലേക്ക്</translation> <translation id="8331626408530291785">മുകളിലേക്ക് സ്ക്രോള് ചെയ്യൂ</translation> -<translation id="4773379706300191099"><ph name="EXTENSION_NAME"/> എന്നതിൽ നിന്നുള്ള അറിയിപ്പുകൾ പ്രവർത്തനരഹിതമാക്കുക</translation> <translation id="7907591526440419938">ഫയല് തുറക്കുക</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> hours ago</translation> <translation id="815598010540052116">താഴേക്ക് സ്ക്രോള്ചെയ്യൂ</translation> +<translation id="6808150112686056157">മീഡിയ നിർത്തുക</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">പുനഃസ്ഥാപിക്കുക</translation> <translation id="1243314992276662751">അപ്ലോഡുചെയ്യുക</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">സഹായം</translation> +<translation id="6699343763173986273">അടുത്ത മീഡിയ ട്രാക്ക്</translation> <translation id="8226233771743600312">ഒരു ദിവസത്തേക്ക് ശല്യപ്പെടുത്തരുത്</translation> <translation id="7457942297256758195">എല്ലാം മായ്ക്കുക</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">ചെറുതാക്കുക</translation> <translation id="6394627529324717982">കോമ</translation> -<translation id="4469842253116033348"><ph name="SITE"/> ല് നിന്നുള്ള വിജ്ഞാപനങ്ങള് അപ്രാപ്തമാക്കുക</translation> <translation id="3036649622769666520">ഫയലുകള് തുറക്കുക</translation> <translation id="8328145009876646418">ഇടത് അഗ്രം</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> സെക്കൻഡ്</translation> diff --git a/chromium/ui/base/strings/ui_strings_mr.xtb b/chromium/ui/base/strings/ui_strings_mr.xtb index a21baf7ae77..d8f026de83d 100644 --- a/chromium/ui/base/strings/ui_strings_mr.xtb +++ b/chromium/ui/base/strings/ui_strings_mr.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">सूचना केंद्र</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> मिनिटे शिल्लक</translation> <translation id="5613020302032141669">Left Arrow</translation> +<translation id="4971687151119236543">मीडिया मागील ट्रॅक</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> फाइल (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> से</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> तास</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">मीडिया प्ले करा/विराम द्या</translation> <translation id="2148716181193084225">आज</translation> <translation id="7960078400008666149">एक तास व्यत्यय आणू नका</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> mins ago</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">उजवे स्क्रोल करा</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> तास बाकी</translation> +<translation id="1413622004203049571"><ph name="NOTIFIER_NAME"/> वरील सूचना अक्षम करा</translation> <translation id="2666092431469916601">शीर्ष</translation> <translation id="8331626408530291785">वर स्क्रोल करा</translation> -<translation id="4773379706300191099"><ph name="EXTENSION_NAME"/> वरील सूचना अक्षम करा</translation> <translation id="7907591526440419938">फाइल उघडा</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> hours ago</translation> <translation id="815598010540052116">खाली स्क्रोल करा</translation> +<translation id="6808150112686056157">मीडिया थांबवा</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">पुनर्संचयित करा</translation> <translation id="1243314992276662751">अपलोड करा</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">मदत</translation> +<translation id="6699343763173986273">मीडिया पुढील ट्रॅक</translation> <translation id="8226233771743600312">एक दिवस व्यत्यय आणू नका</translation> <translation id="7457942297256758195">सर्व साफ करा</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">लहान करा</translation> <translation id="6394627529324717982">स्वल्पविराम</translation> -<translation id="4469842253116033348"><ph name="SITE"/> कडील सूचना अक्षम करा</translation> <translation id="3036649622769666520">फायली उघडा</translation> <translation id="8328145009876646418">डावे काठ</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> सेकंद</translation> diff --git a/chromium/ui/base/strings/ui_strings_ms.xtb b/chromium/ui/base/strings/ui_strings_ms.xtb index 51fbc90f5bd..68a15bbfc46 100644 --- a/chromium/ui/base/strings/ui_strings_ms.xtb +++ b/chromium/ui/base/strings/ui_strings_ms.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Pusat Pemberitahuan</translation> <translation id="7470933019269157899">Tinggal <ph name="NUMBER_DEFAULT"/> minit</translation> <translation id="5613020302032141669">Anak Panah Kiri</translation> +<translation id="4971687151119236543">Lagu Media Sebelumnya</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> Fail (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> minit yang lalu</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> saat</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> jam</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">Main/Jeda Media</translation> <translation id="2148716181193084225">Hari ini</translation> <translation id="7960078400008666149">Jangan ganggu selama sejam</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> minit yang lalu</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">AtsHlmn</translation> <translation id="4588090240171750605">Tatal ke Kanan</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> jam lagi</translation> +<translation id="1413622004203049571">Lumpuhkan pemberitahuan daripada <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Atas</translation> <translation id="8331626408530291785">Tatal Ke Atas</translation> -<translation id="4773379706300191099">Lumpuhkan pemberitahuan daripada <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Buka Fail</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> hari lagi</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> jam lalu</translation> <translation id="815598010540052116">Tatal Ke Bawah</translation> +<translation id="6808150112686056157">Media Berhenti</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> minit lagi</translation> <translation id="3157931365184549694">Pulihkan</translation> <translation id="1243314992276662751">Muat naik</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> minit yang lalu</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Bantuan</translation> +<translation id="6699343763173986273">Lagu Media Seterusnya</translation> <translation id="8226233771743600312">Jangan ganggu selama sehari</translation> <translation id="7457942297256758195">Kosongkan Semua</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> hari yang lalu</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> hari yang lalu</translation> <translation id="5941711191222866238">Minimumkan</translation> <translation id="6394627529324717982">Koma</translation> -<translation id="4469842253116033348">Lumpuhkan pemberitahuan daripada <ph name="SITE"/></translation> <translation id="3036649622769666520">Buka Fail</translation> <translation id="8328145009876646418">Tepi Kiri</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> saat</translation> diff --git a/chromium/ui/base/strings/ui_strings_nl.xtb b/chromium/ui/base/strings/ui_strings_nl.xtb index bced1229f7e..d4b81d423b5 100644 --- a/chromium/ui/base/strings/ui_strings_nl.xtb +++ b/chromium/ui/base/strings/ui_strings_nl.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Meldingscentrum</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> minuten resterend</translation> <translation id="5613020302032141669">Pijl-links</translation> +<translation id="4971687151119236543">Vorige track voor media</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/>-bestand (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> seconden</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> uur</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> kB/s</translation> +<translation id="8394908167088220973">Media afspelen/onderbreken</translation> <translation id="2148716181193084225">Vandaag</translation> <translation id="7960078400008666149">Een uur niet storen</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> minuten geleden</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Naar rechts bladeren</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> uur resterend</translation> +<translation id="1413622004203049571">Meldingen van <ph name="NOTIFIER_NAME"/> uitschakelen</translation> <translation id="2666092431469916601">Boven</translation> <translation id="8331626408530291785">Omhoog bladeren</translation> -<translation id="4773379706300191099">Meldingen van <ph name="EXTENSION_NAME"/> uitschakelen</translation> <translation id="7907591526440419938">Bestand openen</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> uur geleden</translation> <translation id="815598010540052116">Omlaag bladeren</translation> +<translation id="6808150112686056157">Media stoppen</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Herstellen</translation> <translation id="1243314992276662751">Uploaden</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> minuten geleden</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Help</translation> +<translation id="6699343763173986273">Volgende track voor media</translation> <translation id="8226233771743600312">Een dag niet storen</translation> <translation id="7457942297256758195">Alles wissen</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> dagen geleden</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Minimaliseren</translation> <translation id="6394627529324717982">Komma</translation> -<translation id="4469842253116033348">Meldingen van <ph name="SITE"/> uitschakelen</translation> <translation id="3036649622769666520">Bestanden openen</translation> <translation id="8328145009876646418">Linkerzijde</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> seconden</translation> diff --git a/chromium/ui/base/strings/ui_strings_no.xtb b/chromium/ui/base/strings/ui_strings_no.xtb index 5f2cac11a18..6e4a12f93d3 100644 --- a/chromium/ui/base/strings/ui_strings_no.xtb +++ b/chromium/ui/base/strings/ui_strings_no.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Varselsenter</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> minutter igjen</translation> <translation id="5613020302032141669">Pil venstre</translation> +<translation id="4971687151119236543">Media – forrige spor</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> Fil (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> sekunder</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> timer</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> kB per sek</translation> +<translation id="8394908167088220973">Media – spill av / pause</translation> <translation id="2148716181193084225">I dag</translation> <translation id="7960078400008666149">Ikke forstyrr i én time</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> mins ago</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Rull mot høyre</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> time igjen</translation> +<translation id="1413622004203049571">Deaktiver varsler fra <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Topp</translation> <translation id="8331626408530291785">Rull opp</translation> -<translation id="4773379706300191099">Deaktiver varsler fra <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Åpne filen</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045">For <ph name="NUMBER_DEFAULT"/> timer siden</translation> <translation id="815598010540052116">Rull ned</translation> +<translation id="6808150112686056157">Media – stopp</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Gjenopprett</translation> <translation id="1243314992276662751">Last opp</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B per sek</translation> <translation id="7649070708921625228">Hjelp</translation> +<translation id="6699343763173986273">Media – neste spor</translation> <translation id="8226233771743600312">Ikke forstyrr i en dag</translation> <translation id="7457942297256758195">Fjern alle</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Minimer</translation> <translation id="6394627529324717982">Komma</translation> -<translation id="4469842253116033348">Deaktiver varslinger fra <ph name="SITE"/></translation> <translation id="3036649622769666520">Åpne filer</translation> <translation id="8328145009876646418">Venstre kant</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> sekunder</translation> diff --git a/chromium/ui/base/strings/ui_strings_pl.xtb b/chromium/ui/base/strings/ui_strings_pl.xtb index 43aa6a4bd6b..4051dd44f15 100644 --- a/chromium/ui/base/strings/ui_strings_pl.xtb +++ b/chromium/ui/base/strings/ui_strings_pl.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Centrum powiadomień</translation> <translation id="7470933019269157899">Pozostało <ph name="NUMBER_DEFAULT"/> minut</translation> <translation id="5613020302032141669">Strzałka w lewo</translation> +<translation id="4971687151119236543">Poprzedni utwór multimedialny</translation> <translation id="8602707065186045623">Plik <ph name="SAVEAS_EXTENSION_TYPE"/> (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> s</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> godz.</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> kB/s</translation> +<translation id="8394908167088220973">Odtwórz/wstrzymaj multimedia</translation> <translation id="2148716181193084225">Dzisiaj</translation> <translation id="7960078400008666149">Nie przeszkadzać przez godzinę</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> min temu</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Przewiń w prawo</translation> <translation id="7414887922320653780">Pozostała <ph name="NUMBER_ONE"/> godzina</translation> +<translation id="1413622004203049571">Wyłącz powiadomienia z <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Do góry</translation> <translation id="8331626408530291785">Przewiń w górę</translation> -<translation id="4773379706300191099">Wyłącz powiadomienia z <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Otwórz plik</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> godz. temu</translation> <translation id="815598010540052116">Przewiń w dół</translation> +<translation id="6808150112686056157">Zatrzymaj multimedia</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Przywróć</translation> <translation id="1243314992276662751">Prześlij</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Pomoc</translation> +<translation id="6699343763173986273">Następny utwór multimedialny</translation> <translation id="8226233771743600312">Nie przeszkadzać przez jeden dzień</translation> <translation id="7457942297256758195">Wyczyść wszystkie</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> dni temu</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Minimalizuj</translation> <translation id="6394627529324717982">Przecinek</translation> -<translation id="4469842253116033348">Wyłącz powiadomienia z witryny <ph name="SITE"/></translation> <translation id="3036649622769666520">Otwórz pliki</translation> <translation id="8328145009876646418">Krawędź po lewej</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> seconds</translation> diff --git a/chromium/ui/base/strings/ui_strings_pt-BR.xtb b/chromium/ui/base/strings/ui_strings_pt-BR.xtb index 90d7f8a3951..5472366e9a4 100644 --- a/chromium/ui/base/strings/ui_strings_pt-BR.xtb +++ b/chromium/ui/base/strings/ui_strings_pt-BR.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Central de Notificações</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> minutos restantes</translation> <translation id="5613020302032141669">Seta para a esquerda</translation> +<translation id="4971687151119236543">Faixa anterior da mídia</translation> <translation id="8602707065186045623">Arquivo <ph name="SAVEAS_EXTENSION_TYPE"/> (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> s</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> horas</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">Reproduzir/pausar mídia</translation> <translation id="2148716181193084225">Hoje</translation> <translation id="7960078400008666149">Não perturbe por uma hora</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> mins ago</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Percorrer à direita</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> hora restante</translation> +<translation id="1413622004203049571">Desativar notificações de <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Parte superior</translation> <translation id="8331626408530291785">Percorrer para cima</translation> -<translation id="4773379706300191099">Desativar notificações de <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Abrir arquivo</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> horas atrás</translation> <translation id="815598010540052116">Percorrer para baixo</translation> +<translation id="6808150112686056157">Parar mídia</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Restaurar</translation> <translation id="1243314992276662751">Fazer upload</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Ajuda</translation> +<translation id="6699343763173986273">Próxima faixa da mídia</translation> <translation id="8226233771743600312">Não perturbe por um dia</translation> <translation id="7457942297256758195">Limpar tudo</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Minimizar</translation> <translation id="6394627529324717982">Vírgula</translation> -<translation id="4469842253116033348">Desativar notificações de <ph name="SITE"/></translation> <translation id="3036649622769666520">Abrir arquivos</translation> <translation id="8328145009876646418">Borda esquerda</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> segundos</translation> diff --git a/chromium/ui/base/strings/ui_strings_pt-PT.xtb b/chromium/ui/base/strings/ui_strings_pt-PT.xtb index 76369e75a2e..5f633635103 100644 --- a/chromium/ui/base/strings/ui_strings_pt-PT.xtb +++ b/chromium/ui/base/strings/ui_strings_pt-PT.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Centro de Notificações</translation> <translation id="7470933019269157899">Faltam <ph name="NUMBER_DEFAULT"/> minutos</translation> <translation id="5613020302032141669">Seta para a esquerda</translation> +<translation id="4971687151119236543">Faixa anterior de multimédia</translation> <translation id="8602707065186045623">Ficheiro <ph name="SAVEAS_EXTENSION_TYPE"/> (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> seg.</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> horas</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">Reproduzir/interromper multimédia</translation> <translation id="2148716181193084225">Hoje</translation> <translation id="7960078400008666149">Não incomodar durante uma hora</translation> <translation id="4373894838514502496">Há <ph name="NUMBER_FEW"/> min.</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Deslocar-se para a direita</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> hora restante</translation> +<translation id="1413622004203049571">Desativar notificações de <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Parte superior</translation> <translation id="8331626408530291785">Deslocar-se para cima</translation> -<translation id="4773379706300191099">Desativar notificações de <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Abrir ficheiro</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045">Há <ph name="NUMBER_DEFAULT"/> horas</translation> <translation id="815598010540052116">Deslocar-se para baixo</translation> +<translation id="6808150112686056157">Parar multimédia</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Restaurar</translation> <translation id="1243314992276662751">Carregar</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497">Há <ph name="NUMBER_MANY"/> min.</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Ajuda</translation> +<translation id="6699343763173986273">Faixa seguinte de multimédia</translation> <translation id="8226233771743600312">Não incomodar durante um dia</translation> <translation id="7457942297256758195">Limpar Tudo</translation> <translation id="822618367988303761">Há <ph name="NUMBER_TWO"/> dias</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Minimizar</translation> <translation id="6394627529324717982">Vírgula</translation> -<translation id="4469842253116033348">Desactivar notificações de <ph name="SITE"/></translation> <translation id="3036649622769666520">Abrir ficheiros</translation> <translation id="8328145009876646418">Margem esquerda</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> segundos</translation> diff --git a/chromium/ui/base/strings/ui_strings_ro.xtb b/chromium/ui/base/strings/ui_strings_ro.xtb index 4f1ed1ae442..b2d57a05223 100644 --- a/chromium/ui/base/strings/ui_strings_ro.xtb +++ b/chromium/ui/base/strings/ui_strings_ro.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Centrul pentru notificări</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> minute rămase</translation> <translation id="5613020302032141669">Săgeata spre stânga</translation> +<translation id="4971687151119236543">Melodia anterioară din conținutul media</translation> <translation id="8602707065186045623">Fișier <ph name="SAVEAS_EXTENSION_TYPE"/> (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918">Cu <ph name="NUMBER_ZERO"/> minute în urmă</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> secunde</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> ore</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KO/s</translation> +<translation id="8394908167088220973">Redați/întrerupeți conținutul media</translation> <translation id="2148716181193084225">Astăzi</translation> <translation id="7960078400008666149">Nu deranja o oră</translation> <translation id="4373894838514502496">Cu <ph name="NUMBER_FEW"/> minute în urmă</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp (o pagină mai sus)</translation> <translation id="4588090240171750605">Derulați spre dreapta</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> oră rămasă</translation> +<translation id="1413622004203049571">Dezactivați notificările de la <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Sus</translation> <translation id="8331626408530291785">Derulați în sus</translation> -<translation id="4773379706300191099">Dezactivați notificările de la <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Deschideți fișierul</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> zile rămase</translation> <translation id="1293699935367580298">Esc (Ieșiți)</translation> <translation id="2797524280730715045">Cu <ph name="NUMBER_DEFAULT"/> (de) ore în urmă</translation> <translation id="815598010540052116">Derulați în jos</translation> +<translation id="6808150112686056157">Opriți conținutul media</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> minute rămase</translation> <translation id="3157931365184549694">Restabiliți</translation> <translation id="1243314992276662751">Încărcați</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497">Cu <ph name="NUMBER_MANY"/> (de) minute în urmă</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> O/s</translation> <translation id="7649070708921625228">Ajutor</translation> +<translation id="6699343763173986273">Melodia următoare din conținutul media</translation> <translation id="8226233771743600312">Nu deranja o zi</translation> <translation id="7457942297256758195">Ștergeți-le pe toate</translation> <translation id="822618367988303761">Cu <ph name="NUMBER_TWO"/> zile în urmă</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496">Cu <ph name="NUMBER_ZERO"/> zile în urmă</translation> <translation id="5941711191222866238">Minimizați</translation> <translation id="6394627529324717982">Virgulă</translation> -<translation id="4469842253116033348">Dezactivați notificările de la <ph name="SITE"/></translation> <translation id="3036649622769666520">Deschideți fișierele</translation> <translation id="8328145009876646418">Marginea stângă</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> secunde</translation> diff --git a/chromium/ui/base/strings/ui_strings_ru.xtb b/chromium/ui/base/strings/ui_strings_ru.xtb index 32dfd2c2fd1..dd7f2c37ac2 100644 --- a/chromium/ui/base/strings/ui_strings_ru.xtb +++ b/chromium/ui/base/strings/ui_strings_ru.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Центр оповещений</translation> <translation id="7470933019269157899">Осталось <ph name="NUMBER_DEFAULT"/> минут</translation> <translation id="5613020302032141669">Стрелка влево</translation> +<translation id="4971687151119236543">Предыдущий трек</translation> <translation id="8602707065186045623">Файл <ph name="SAVEAS_EXTENSION_TYPE"/> (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> сек.</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> ч.</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> КБ/с</translation> +<translation id="8394908167088220973">Воспроизведение/пауза</translation> <translation id="2148716181193084225">Сегодня</translation> <translation id="7960078400008666149">Не беспокоить (1 час)</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> мин. назад</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Прокрутка вправо</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> ч.</translation> +<translation id="1413622004203049571">Отключить оповещения от <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Наверх</translation> <translation id="8331626408530291785">Прокрутка вверх</translation> -<translation id="4773379706300191099">Отключить оповещения от <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Открытие файла</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> ч. назад</translation> <translation id="815598010540052116">Прокрутка вниз</translation> +<translation id="6808150112686056157">Остановить</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Восстановить</translation> <translation id="1243314992276662751">Загрузить</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> Б/с</translation> <translation id="7649070708921625228">Справка</translation> +<translation id="6699343763173986273">Следующий трек</translation> <translation id="8226233771743600312">Не беспокоить (1 день)</translation> <translation id="7457942297256758195">Очистить все</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Свернуть</translation> <translation id="6394627529324717982">Запятая</translation> -<translation id="4469842253116033348">Отключить уведомления с этого адреса: <ph name="SITE"/></translation> <translation id="3036649622769666520">Открытие файлов</translation> <translation id="8328145009876646418">Левый край</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> сек.</translation> diff --git a/chromium/ui/base/strings/ui_strings_sk.xtb b/chromium/ui/base/strings/ui_strings_sk.xtb index 00fc533fcfb..0996629ec1c 100644 --- a/chromium/ui/base/strings/ui_strings_sk.xtb +++ b/chromium/ui/base/strings/ui_strings_sk.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Centrum upozornení</translation> <translation id="7470933019269157899">Zostáva <ph name="NUMBER_DEFAULT"/> minút</translation> <translation id="5613020302032141669">Šípka doľava</translation> +<translation id="4971687151119236543">Média – predchádzajúca stopa</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> Súbor (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252">Počet sekúnd: <ph name="NUMBER_TWO"/></translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401">Počet hodín: <ph name="NUMBER_MANY"/></translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> kB/s</translation> +<translation id="8394908167088220973">Média – prehrať / pozastaviť</translation> <translation id="2148716181193084225">Dnes</translation> <translation id="7960078400008666149">Nerušiť jednu hodinu</translation> <translation id="4373894838514502496">Pred <ph name="NUMBER_FEW"/> min</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Rolovať doprava</translation> <translation id="7414887922320653780">Zostáva <ph name="NUMBER_ONE"/> hodina</translation> +<translation id="1413622004203049571">Zakázať upozornenia od <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Vrch</translation> <translation id="8331626408530291785">Rolovať nahor</translation> -<translation id="4773379706300191099">Vypnúť prijímanie upozornení od rozšírenia <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Otvoriť súbor</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045">Pred <ph name="NUMBER_DEFAULT"/> hodinami</translation> <translation id="815598010540052116">Rolovať nadol</translation> +<translation id="6808150112686056157">Médiá – zastaviť</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Obnoviť</translation> <translation id="1243314992276662751">Odovzdať</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Pomocník</translation> +<translation id="6699343763173986273">Média – ďalšia stopa</translation> <translation id="8226233771743600312">Nerušiť jeden deň</translation> <translation id="7457942297256758195">Vymazať všetky</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Minimalizovať</translation> <translation id="6394627529324717982">Čiarka</translation> -<translation id="4469842253116033348">Zakázať upozornenia z webových stránok <ph name="SITE"/></translation> <translation id="3036649622769666520">Otvoriť súbory</translation> <translation id="8328145009876646418">Ľavý okraj</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> sekundy</translation> diff --git a/chromium/ui/base/strings/ui_strings_sl.xtb b/chromium/ui/base/strings/ui_strings_sl.xtb index 6f811ed4d2b..a49f23ce958 100644 --- a/chromium/ui/base/strings/ui_strings_sl.xtb +++ b/chromium/ui/base/strings/ui_strings_sl.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Središče za obvestila</translation> <translation id="7470933019269157899">še <ph name="NUMBER_DEFAULT"/> min</translation> <translation id="5613020302032141669">Puščica levo</translation> +<translation id="4971687151119236543">Prejšnja skladba</translation> <translation id="8602707065186045623">Datoteka <ph name="SAVEAS_EXTENSION_TYPE"/> (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> sek</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> ur</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">Ustavitev/začasna ustavitev</translation> <translation id="2148716181193084225">Danes</translation> <translation id="7960078400008666149">Ne moti eno uro</translation> <translation id="4373894838514502496">Pred <ph name="NUMBER_FEW"/> min</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Pomik desno</translation> <translation id="7414887922320653780">še <ph name="NUMBER_ONE"/> ura</translation> +<translation id="1413622004203049571">Izklop obvestil za <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Na vrh</translation> <translation id="8331626408530291785">Pomik gor</translation> -<translation id="4773379706300191099">Onemogoči obvestila aplikacije <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Odpri datoteko</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045">Pred <ph name="NUMBER_DEFAULT"/> h</translation> <translation id="815598010540052116">Pomik dol</translation> +<translation id="6808150112686056157">Ustavitev</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Obnovi</translation> <translation id="1243314992276662751">Prenesi</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497">Pred <ph name="NUMBER_MANY"/> min</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Pomoč</translation> +<translation id="6699343763173986273">Naslednja skladba</translation> <translation id="8226233771743600312">Ne moti en dan</translation> <translation id="7457942297256758195">Izbriši vse</translation> <translation id="822618367988303761">Pred <ph name="NUMBER_TWO"/> dnevoma</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Pomanjšaj</translation> <translation id="6394627529324717982">Vejica</translation> -<translation id="4469842253116033348">Onemogoči obvestila spletnega mesta <ph name="SITE"/></translation> <translation id="3036649622769666520">Odpri datoteke</translation> <translation id="8328145009876646418">Levi rob</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> sekundi</translation> diff --git a/chromium/ui/base/strings/ui_strings_sr.xtb b/chromium/ui/base/strings/ui_strings_sr.xtb index e036fd1c3d6..c84c2d5f675 100644 --- a/chromium/ui/base/strings/ui_strings_sr.xtb +++ b/chromium/ui/base/strings/ui_strings_sr.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Центар за обавештења</translation> <translation id="7470933019269157899">Преостало је <ph name="NUMBER_DEFAULT"/> минута</translation> <translation id="5613020302032141669">Стрелица налево</translation> +<translation id="4971687151119236543">Претходна песма медија</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> датотека (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> сек.</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401">Сати: <ph name="NUMBER_MANY"/></translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">Пуштање/паузирање медија</translation> <translation id="2148716181193084225">Данас</translation> <translation id="7960078400008666149">Не узнемиравај у периоду од сат времена</translation> <translation id="4373894838514502496">Пре <ph name="NUMBER_FEW"/> минута</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">Page Up</translation> <translation id="4588090240171750605">Помери надесно</translation> <translation id="7414887922320653780">Преостао <ph name="NUMBER_ONE"/> сат</translation> +<translation id="1413622004203049571">Онемогући обавештења од <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Врх</translation> <translation id="8331626408530291785">Помери нагоре</translation> -<translation id="4773379706300191099">Онемогући обавештења из додатка <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Отварање датотеке</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045">Пре <ph name="NUMBER_DEFAULT"/> сата</translation> <translation id="815598010540052116">Помери надоле</translation> +<translation id="6808150112686056157">Заустављање медија</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Поново отвори</translation> <translation id="1243314992276662751">Отпреми</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Помоћ</translation> +<translation id="6699343763173986273">Следећа песма медија</translation> <translation id="8226233771743600312">Не узнемиравај у периоду од једног дана</translation> <translation id="7457942297256758195">Обриши све</translation> <translation id="822618367988303761">Пре <ph name="NUMBER_TWO"/> дана</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Смањи</translation> <translation id="6394627529324717982">Зарез</translation> -<translation id="4469842253116033348">Онемогући обавештења са <ph name="SITE"/></translation> <translation id="3036649622769666520">Отварање датотека</translation> <translation id="8328145009876646418">Лева ивица</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> секунде</translation> diff --git a/chromium/ui/base/strings/ui_strings_sv.xtb b/chromium/ui/base/strings/ui_strings_sv.xtb index d8de713c599..3beabc978d1 100644 --- a/chromium/ui/base/strings/ui_strings_sv.xtb +++ b/chromium/ui/base/strings/ui_strings_sv.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Meddelandecenter</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> minuter kvar</translation> <translation id="5613020302032141669">Vänsterpil</translation> +<translation id="4971687151119236543">Föregående spår</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/>-fil (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> sekunder</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> timmar</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> kB/sek</translation> +<translation id="8394908167088220973">Spela upp/Pausa</translation> <translation id="2148716181193084225">Idag</translation> <translation id="7960078400008666149">Stör inte i en timme</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> mins ago</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Rulla åt höger</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> timmar kvar</translation> +<translation id="1413622004203049571">Inaktivera aviseringar från <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Överst</translation> <translation id="8331626408530291785">Rulla uppåt</translation> -<translation id="4773379706300191099">Inaktivera meddelanden från <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Öppna fil</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045">För <ph name="NUMBER_DEFAULT"/> timmar sedan</translation> <translation id="815598010540052116">Rulla nedåt</translation> +<translation id="6808150112686056157">Stoppa</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Återställ</translation> <translation id="1243314992276662751">Överför</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/sek</translation> <translation id="7649070708921625228">Hjälp</translation> +<translation id="6699343763173986273">Nästa spår</translation> <translation id="8226233771743600312">Stör inte i en dag</translation> <translation id="7457942297256758195">Ta bort alla</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Minimera</translation> <translation id="6394627529324717982">Komma</translation> -<translation id="4469842253116033348">Inaktivera meddelanden från <ph name="SITE"/></translation> <translation id="3036649622769666520">Öppna filer</translation> <translation id="8328145009876646418">Vänsterkant</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> sekunder</translation> diff --git a/chromium/ui/base/strings/ui_strings_sw.xtb b/chromium/ui/base/strings/ui_strings_sw.xtb index 95cdd9bf1f6..efee106b110 100644 --- a/chromium/ui/base/strings/ui_strings_sw.xtb +++ b/chromium/ui/base/strings/ui_strings_sw.xtb @@ -11,8 +11,9 @@ <translation id="1209866192426315618">zimesalia dakika <ph name="NUMBER_DEFAULT"/></translation> <translation id="1801827354178857021">Kikomo</translation> <translation id="1190609913194133056">Kituo cha Arifa</translation> -<translation id="7470933019269157899">Dakika <ph name="NUMBER_DEFAULT"/> zinasalia</translation> +<translation id="7470933019269157899">Zimesalia dakika <ph name="NUMBER_DEFAULT"/></translation> <translation id="5613020302032141669">Mshale Kushoto</translation> +<translation id="4971687151119236543">Wimbo wa Awali wa Media</translation> <translation id="8602707065186045623">Faili ya <ph name="SAVEAS_EXTENSION_TYPE"/> (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918">dakika <ph name="NUMBER_ZERO"/> zilizopita</translation> <translation id="7121570032414343252">zimesalia sekunde <ph name="NUMBER_TWO"/></translation> @@ -32,7 +33,7 @@ <translation id="8666066831007952346">zimesalia siku <ph name="NUMBER_TWO"/></translation> <translation id="6390842777729054533">zimesalia sekunde <ph name="NUMBER_ZERO"/></translation> <translation id="3909791450649380159">&Kata</translation> -<translation id="2560788951337264832">Dakika <ph name="NUMBER_ZERO"/> zinasalia</translation> +<translation id="2560788951337264832">Zimesalia dakika <ph name="NUMBER_ZERO"/></translation> <translation id="688711909580084195">Ukurasa wa Wavuti usio na Kichwa</translation> <translation id="3353284378027041011">siku <ph name="NUMBER_FEW"/> zilizopita</translation> <translation id="5076340679995252485">&Bandika</translation> @@ -70,7 +71,7 @@ <translation id="4988273303304146523">siku <ph name="NUMBER_DEFAULT"/> zilizopita</translation> <translation id="8428213095426709021">Mipangilio</translation> <translation id="2497284189126895209">Faili zote</translation> -<translation id="7487278341251176613">Dakika <ph name="NUMBER_TWO"/> zinasalia</translation> +<translation id="7487278341251176613">Zimesalia dakika <ph name="NUMBER_TWO"/></translation> <translation id="5110450810124758964">siku <ph name="NUMBER_ONE"/> iliyopita</translation> <translation id="2820806154655529776">sekunde <ph name="NUMBER_ONE"/></translation> <translation id="7814458197256864873">&Nakili</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401">saa <ph name="NUMBER_MANY"/></translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">Cheza Media/Sitisha</translation> <translation id="2148716181193084225">Leo</translation> <translation id="7960078400008666149">Usinisumbue kwa saa moja</translation> <translation id="4373894838514502496">dakika <ph name="NUMBER_FEW"/> zilizopita</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Sogeza Kulia</translation> <translation id="7414887922320653780">limesalia saa <ph name="NUMBER_ONE"/></translation> +<translation id="1413622004203049571">Zima arifa kutoka <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Ya Juu</translation> <translation id="8331626408530291785">Sogeza Juu</translation> -<translation id="4773379706300191099">Zima arifa kutoka <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Fungua Faili</translation> <translation id="2864069933652346933">zimesalia siku <ph name="NUMBER_ZERO"/></translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045">Saa <ph name="NUMBER_DEFAULT"/> zilizopita</translation> <translation id="815598010540052116">Sogeza Chini</translation> +<translation id="6808150112686056157">Simamisha Media</translation> <translation id="1308727876662951186">zimesalia dakika <ph name="NUMBER_ZERO"/></translation> <translation id="3157931365184549694">Rejesha</translation> <translation id="1243314992276662751">Pakia</translation> @@ -132,7 +135,7 @@ <translation id="1285266685456062655">Saa <ph name="NUMBER_FEW"/> zilizopita</translation> <translation id="6918245111648057970">Ruhusu arifa kutoka kwa wafuatao kwa kila mtumiaji:</translation> <translation id="5489830104927132166">Sekunde <ph name="NUMBER_ONE"/></translation> -<translation id="3994835489895548312">Dakika <ph name="NUMBER_MANY"/> zinasalia</translation> +<translation id="3994835489895548312">Zimesalia dakika <ph name="NUMBER_MANY"/></translation> <translation id="6358975074282722691">sekunde <ph name="NUMBER_TWO"/> zilizopita</translation> <translation id="520299402983819650">PB <ph name="QUANTITY"/></translation> <translation id="2983818520079887040">Mipangilio...</translation> @@ -154,11 +157,12 @@ <translation id="4860787810836767172">sekunde <ph name="NUMBER_FEW"/> zilizopita</translation> <translation id="2297836609126180313"><ph name="QUANTITY"/> TB/s</translation> <translation id="6956540737482608074">Dakika <ph name="NUMBER_ZERO"/></translation> -<translation id="1858722859751911017">Dakika <ph name="NUMBER_FEW"/> zinasalia</translation> +<translation id="1858722859751911017">Zimesalia dakika <ph name="NUMBER_FEW"/></translation> <translation id="6040143037577758943">Funga</translation> <translation id="1101671447232096497">dakika <ph name="NUMBER_MANY"/> zilizopita</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">Usaidizi</translation> +<translation id="6699343763173986273">Wimbo Unaofuata kwenye Media</translation> <translation id="8226233771743600312">Usinisumbue kwa siku moja</translation> <translation id="7457942297256758195">Futa Zote</translation> <translation id="822618367988303761">siku <ph name="NUMBER_TWO"/> zilizopita</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496">siku <ph name="NUMBER_ZERO"/> zilizopita</translation> <translation id="5941711191222866238">Punguza</translation> <translation id="6394627529324717982">Koma</translation> -<translation id="4469842253116033348">Lemaza arifa kutoka <ph name="SITE"/></translation> <translation id="3036649622769666520">Fungua Mafaili</translation> <translation id="8328145009876646418">Ncha ya Kushoto</translation> <translation id="7372005818821648611">Sekunde <ph name="NUMBER_TWO"/></translation> diff --git a/chromium/ui/base/strings/ui_strings_ta.xtb b/chromium/ui/base/strings/ui_strings_ta.xtb index 008279fb712..ab43f69fe72 100644 --- a/chromium/ui/base/strings/ui_strings_ta.xtb +++ b/chromium/ui/base/strings/ui_strings_ta.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">அறிவிப்பு மையம்</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> நிமிடங்கள் உள்ளன</translation> <translation id="5613020302032141669">இடது அம்பு</translation> +<translation id="4971687151119236543">ஊடகத்தின் முந்தைய டிராக்</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/>கோப்பு(.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> வினாடிகள்</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> மணிநேரம்</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> கி.பை./வி</translation> +<translation id="8394908167088220973">ஊடகத்தை இயக்கு/இடைநிறுத்து</translation> <translation id="2148716181193084225">இன்று</translation> <translation id="7960078400008666149">ஒரு மணிநேரத்திற்குத் தொந்தரவு செய்ய வேண்டாம்</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> mins ago</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">வலப்புறம் உருட்டு</translation> <translation id="7414887922320653780">இன்னும் <ph name="NUMBER_ONE"/> மணிநேரம் உள்ளது</translation> +<translation id="1413622004203049571"><ph name="NOTIFIER_NAME"/> இடமிருந்து வரும் அறிவிப்புகளை முடக்கு</translation> <translation id="2666092431469916601">மேலே</translation> <translation id="8331626408530291785">மேலே உருட்டு</translation> -<translation id="4773379706300191099"><ph name="EXTENSION_NAME"/> இலிருந்து வரும் அறிவிப்புகளை முடக்கு</translation> <translation id="7907591526440419938">கோப்பைத் திற</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> hours ago</translation> <translation id="815598010540052116">கீழே உருட்டு</translation> +<translation id="6808150112686056157">ஊடகத்தை நிறுத்து</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">மீட்டமை</translation> <translation id="1243314992276662751">பதிவேற்று</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> பை/வி</translation> <translation id="7649070708921625228">உதவி</translation> +<translation id="6699343763173986273">ஊடகத்தின் அடுத்த டிராக்</translation> <translation id="8226233771743600312">ஒரு நாள் தொந்தரவு செய்ய வேண்டாம்</translation> <translation id="7457942297256758195">அனைத்தையும் அழி</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">சிறிதாக்கு</translation> <translation id="6394627529324717982">கமா</translation> -<translation id="4469842253116033348"><ph name="SITE"/> இலிருந்து வரும் அறிவிப்புகளை முடக்கு</translation> <translation id="3036649622769666520">கோப்புகளைத் திற</translation> <translation id="8328145009876646418">இடதுபுற முனை</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> வினாடிகள்</translation> diff --git a/chromium/ui/base/strings/ui_strings_te.xtb b/chromium/ui/base/strings/ui_strings_te.xtb index e94d3eba4b1..bd65f556886 100644 --- a/chromium/ui/base/strings/ui_strings_te.xtb +++ b/chromium/ui/base/strings/ui_strings_te.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">నోటిఫికేషన్ కేంద్రం</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> నిమిషాలు మిగిలి ఉన్నాయి</translation> <translation id="5613020302032141669">ఎడమ బాణం</translation> +<translation id="4971687151119236543">మీడియా మునుపటి ట్రాక్</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> ఫైల్ (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> సెకన్లు</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> గంటలు</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/సె</translation> +<translation id="8394908167088220973">మీడియా ప్లే/పాజ్</translation> <translation id="2148716181193084225">ఈ రోజు</translation> <translation id="7960078400008666149">ఒక గంటపాటు అంతరాయం కలిగించవద్దు</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> mins ago</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">కుడికి స్క్రోల్ చెయ్యి</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> గంటలు మిగిలా యి</translation> +<translation id="1413622004203049571"><ph name="NOTIFIER_NAME"/> నుండి వచ్చే నోటిఫికేషన్లను నిలిపివేయి</translation> <translation id="2666092431469916601">పైన</translation> <translation id="8331626408530291785">పైకి స్క్రోల్ చెయ్యి</translation> -<translation id="4773379706300191099"><ph name="EXTENSION_NAME"/> నుండి నోటిఫికేషన్లను నిలిపివేయి</translation> <translation id="7907591526440419938">ఫైల్ను తెరువు</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> hours ago</translation> <translation id="815598010540052116">క్రిందికి స్క్రోల్ చేయి</translation> +<translation id="6808150112686056157">మీడియా ఆపివేయి</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">పునరుద్ధరించు</translation> <translation id="1243314992276662751">అప్లోడ్ చేయి</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">సహాయం</translation> +<translation id="6699343763173986273">మీడియా తదుపరి ట్రాక్</translation> <translation id="8226233771743600312">ఒక రోజుపాటు అంతరాయం కలిగించవద్దు</translation> <translation id="7457942297256758195">అన్నీ క్లియర్ చేయి</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">కనిష్టీకరించు</translation> <translation id="6394627529324717982">కామా</translation> -<translation id="4469842253116033348"><ph name="SITE"/> నుండి ప్రకటనలను ఆపివెయ్యి</translation> <translation id="3036649622769666520">ఫైళ్ళను తెరువు</translation> <translation id="8328145009876646418">ఎడమ హద్దు</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> సెకన్లు</translation> diff --git a/chromium/ui/base/strings/ui_strings_th.xtb b/chromium/ui/base/strings/ui_strings_th.xtb index 4ebb6112e4e..13a7accff80 100644 --- a/chromium/ui/base/strings/ui_strings_th.xtb +++ b/chromium/ui/base/strings/ui_strings_th.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">ศูนย์การแจ้งเตือน</translation> <translation id="7470933019269157899">เหลือ <ph name="NUMBER_DEFAULT"/> นาที</translation> <translation id="5613020302032141669">ลูกศรซ้าย</translation> +<translation id="4971687151119236543">แทร็กก่อนหน้าของสื่อ</translation> <translation id="8602707065186045623">ไฟล์ <ph name="SAVEAS_EXTENSION_TYPE"/> (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> วินาที</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> ชั่วโมง</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/วินาที</translation> +<translation id="8394908167088220973">เล่น/หยุดสื่อชั่วคราว</translation> <translation id="2148716181193084225">วันนี้</translation> <translation id="7960078400008666149">ห้ามรบกวนเป็นเวลาหนึ่งชั่วโมง</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> นาทีที่ผ่านมา</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">เลื่อนทางขวา</translation> <translation id="7414887922320653780">เหลือ <ph name="NUMBER_ONE"/> ชั่วโมง</translation> +<translation id="1413622004203049571">ปิดการแจ้งเตือนจาก <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">ด้านบน</translation> <translation id="8331626408530291785">เลื่อนขึ้น</translation> -<translation id="4773379706300191099">ปิดการแจ้งเตือนจาก <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">เปิดไฟล์</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> ชั่วโมงที่ผ่านมา</translation> <translation id="815598010540052116">เลื่อนลง</translation> +<translation id="6808150112686056157">หยุดสื่อ</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">คืนค่า</translation> <translation id="1243314992276662751">อัปโหลด</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> นาทีที่ผ่านมา</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/วินาที</translation> <translation id="7649070708921625228">ช่วยเหลือ</translation> +<translation id="6699343763173986273">แทร็กถัดไปของสื่อ</translation> <translation id="8226233771743600312">ห้ามรบกวนเป็นเวลาหนึ่งวัน</translation> <translation id="7457942297256758195">ล้างทั้งหมด</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> วันที่ผ่านมา</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">ย่อ</translation> <translation id="6394627529324717982">จุลภาค</translation> -<translation id="4469842253116033348">ปิดการใช้งานการแจ้งเตือนจาก <ph name="SITE"/></translation> <translation id="3036649622769666520">เปิดไฟล์</translation> <translation id="8328145009876646418">ขอบซ้าย</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> seconds</translation> diff --git a/chromium/ui/base/strings/ui_strings_tr.xtb b/chromium/ui/base/strings/ui_strings_tr.xtb index b3b02cb551c..1d76aa7f9e2 100644 --- a/chromium/ui/base/strings/ui_strings_tr.xtb +++ b/chromium/ui/base/strings/ui_strings_tr.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Bildirim Merkezi</translation> <translation id="7470933019269157899"><ph name="NUMBER_DEFAULT"/> dakika kaldı</translation> <translation id="5613020302032141669">Sol Ok</translation> +<translation id="4971687151119236543">Medya Önceki Parça</translation> <translation id="8602707065186045623">Dosyayı <ph name="SAVEAS_EXTENSION_TYPE"/> (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> saniye</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> saat</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/sn</translation> +<translation id="8394908167088220973">Medyayı Oynat/Duraklat</translation> <translation id="2148716181193084225">Bugün</translation> <translation id="7960078400008666149">Bir saat süreyle rahatsız etmeyin</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> dakika önce</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Sağa Kaydır</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> saat kaldı</translation> +<translation id="1413622004203049571"><ph name="NOTIFIER_NAME"/> bildirimlerini devre dışı bırak</translation> <translation id="2666092431469916601">Üst</translation> <translation id="8331626408530291785">Yukarı Kaydır</translation> -<translation id="4773379706300191099"><ph name="EXTENSION_NAME"/> bildirimlerini devre dışı bırak</translation> <translation id="7907591526440419938">Dosya Aç</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> saat önce</translation> <translation id="815598010540052116">Aşağı Kaydır</translation> +<translation id="6808150112686056157">Medyayı Durdur</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Geri yükle</translation> <translation id="1243314992276662751">Yükle</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> dakika önce</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/sn</translation> <translation id="7649070708921625228">Yardım</translation> +<translation id="6699343763173986273">Medya Sonraki Parça</translation> <translation id="8226233771743600312">Bir gün süreyle rahatsız etmeyin</translation> <translation id="7457942297256758195">Tümünü Temizle</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> gün önce</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Simge durumuna küçült</translation> <translation id="6394627529324717982">Virgül</translation> -<translation id="4469842253116033348"><ph name="SITE"/> bildirimlerini devre dışı bırak</translation> <translation id="3036649622769666520">Dosya Aç</translation> <translation id="8328145009876646418">Sol Kenar</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> seconds</translation> diff --git a/chromium/ui/base/strings/ui_strings_uk.xtb b/chromium/ui/base/strings/ui_strings_uk.xtb index 1287a629908..22cdf216e7a 100644 --- a/chromium/ui/base/strings/ui_strings_uk.xtb +++ b/chromium/ui/base/strings/ui_strings_uk.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Центр сповіщень</translation> <translation id="7470933019269157899">Залишилося <ph name="NUMBER_DEFAULT"/> хвилини</translation> <translation id="5613020302032141669">Курсор ліворуч</translation> +<translation id="4971687151119236543">Попередня композиція</translation> <translation id="8602707065186045623">файл <ph name="SAVEAS_EXTENSION_TYPE"/> (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> secs</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> годин</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> Кб/сек.</translation> +<translation id="8394908167088220973">Відтворити чи призупинити</translation> <translation id="2148716181193084225">Сьогодні</translation> <translation id="7960078400008666149">Не турбувати впродовж однієї години</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> хв. тому</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">Прокрутка вправо</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> година залишилась</translation> +<translation id="1413622004203049571">Вимкнути сповіщення від <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Верх</translation> <translation id="8331626408530291785">Прокрутка вгору</translation> -<translation id="4773379706300191099">Вимкнути сповіщення з розширення <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Відкрити файл</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> год. тому</translation> <translation id="815598010540052116">Прокрутка вниз</translation> +<translation id="6808150112686056157">Зупинити</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Відновити</translation> <translation id="1243314992276662751">Завантажити</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> б/сек.</translation> <translation id="7649070708921625228">Довідка</translation> +<translation id="6699343763173986273">Наступна композиція</translation> <translation id="8226233771743600312">Не турбувати впродовж одного дня</translation> <translation id="7457942297256758195">Очистити все</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Зменшити</translation> <translation id="6394627529324717982">Кома</translation> -<translation id="4469842253116033348">Вимкнути сповіщення від <ph name="SITE"/></translation> <translation id="3036649622769666520">Відкрити файли</translation> <translation id="8328145009876646418">Лівий край</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> seconds</translation> diff --git a/chromium/ui/base/strings/ui_strings_vi.xtb b/chromium/ui/base/strings/ui_strings_vi.xtb index b5ef2dff826..7809cc6606f 100644 --- a/chromium/ui/base/strings/ui_strings_vi.xtb +++ b/chromium/ui/base/strings/ui_strings_vi.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">Trung tâm thông báo</translation> <translation id="7470933019269157899">Còn lại <ph name="NUMBER_DEFAULT"/> phút</translation> <translation id="5613020302032141669">Mũi tên Trái</translation> +<translation id="4971687151119236543">Bản nhạc trước của trình phát phương tiện</translation> <translation id="8602707065186045623">Tệp <ph name="SAVEAS_EXTENSION_TYPE"/> (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> giây</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> giờ</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">Phát/Tạm dừng trình phát phương tiện</translation> <translation id="2148716181193084225">Hôm nay</translation> <translation id="7960078400008666149">Không làm phiền trong một giờ</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> mins ago</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">Trang Trên</translation> <translation id="4588090240171750605">Cuộn qua Phải</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> giờ còn lại</translation> +<translation id="1413622004203049571">Tắt thông báo từ <ph name="NOTIFIER_NAME"/></translation> <translation id="2666092431469916601">Hàng đầu</translation> <translation id="8331626408530291785">Cuộn Lên</translation> -<translation id="4773379706300191099">Tắt thông báo từ <ph name="EXTENSION_NAME"/></translation> <translation id="7907591526440419938">Mở Tệp</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Thoát</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> giờ trước</translation> <translation id="815598010540052116">Cuộn Xuống</translation> +<translation id="6808150112686056157">Dừng trình phát phương tiện</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">Khôi phục</translation> <translation id="1243314992276662751">Tải lên</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/giây</translation> <translation id="7649070708921625228">Trợ giúp</translation> +<translation id="6699343763173986273">Bản nhạc tiếp theo của trình phát phương tiện</translation> <translation id="8226233771743600312">Không làm phiền trong một ngày</translation> <translation id="7457942297256758195">Xóa tất cả</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> days ago</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">Thu nhỏ</translation> <translation id="6394627529324717982">Dấu phẩy</translation> -<translation id="4469842253116033348">Vô hiệu hóa thông báo từ <ph name="SITE"/></translation> <translation id="3036649622769666520">Mở Tệp</translation> <translation id="8328145009876646418">Cạnh Bên trái</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> giây</translation> diff --git a/chromium/ui/base/strings/ui_strings_zh-CN.xtb b/chromium/ui/base/strings/ui_strings_zh-CN.xtb index e38ba7895ad..bc02e6203e9 100644 --- a/chromium/ui/base/strings/ui_strings_zh-CN.xtb +++ b/chromium/ui/base/strings/ui_strings_zh-CN.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">通知中心</translation> <translation id="7470933019269157899">还剩 <ph name="NUMBER_DEFAULT"/> 分钟</translation> <translation id="5613020302032141669">向左箭头</translation> +<translation id="4971687151119236543">媒体上一曲</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> 文件 (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> secs</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> hours</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/s</translation> +<translation id="8394908167088220973">媒体播放/暂停</translation> <translation id="2148716181193084225">今天</translation> <translation id="7960078400008666149">1 小时内请勿打扰</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> 分钟前</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">向右滚动</translation> <translation id="7414887922320653780"><ph name="NUMBER_ONE"/> hour left</translation> +<translation id="1413622004203049571">停用来自“<ph name="NOTIFIER_NAME"/>”的通知</translation> <translation id="2666092431469916601">顶部</translation> <translation id="8331626408530291785">向上滚动</translation> -<translation id="4773379706300191099">停用来自“<ph name="EXTENSION_NAME"/>”的通知</translation> <translation id="7907591526440419938">打开文件</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> 小时前</translation> <translation id="815598010540052116">向下滚动</translation> +<translation id="6808150112686056157">媒体停止</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">恢复</translation> <translation id="1243314992276662751">上传</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> 分钟前</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/s</translation> <translation id="7649070708921625228">帮助</translation> +<translation id="6699343763173986273">媒体下一曲</translation> <translation id="8226233771743600312">1 天内请勿打扰</translation> <translation id="7457942297256758195">全部清除</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> 天前</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">最小化</translation> <translation id="6394627529324717982">逗号</translation> -<translation id="4469842253116033348">停用 <ph name="SITE"/> 的通知</translation> <translation id="3036649622769666520">打开文件</translation> <translation id="8328145009876646418">左边缘</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> 秒</translation> diff --git a/chromium/ui/base/strings/ui_strings_zh-TW.xtb b/chromium/ui/base/strings/ui_strings_zh-TW.xtb index 9a1074542a3..8cac9e71a6e 100644 --- a/chromium/ui/base/strings/ui_strings_zh-TW.xtb +++ b/chromium/ui/base/strings/ui_strings_zh-TW.xtb @@ -13,6 +13,7 @@ <translation id="1190609913194133056">通知中心</translation> <translation id="7470933019269157899">剩下 <ph name="NUMBER_DEFAULT"/> 分鐘</translation> <translation id="5613020302032141669">向左鍵</translation> +<translation id="4971687151119236543">上一首媒體曲目</translation> <translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE"/> 檔案 (.<ph name="SAVEAS_EXTENSION_NAME"/>)</translation> <translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation> <translation id="7121570032414343252"><ph name="NUMBER_TWO"/> 秒</translation> @@ -104,6 +105,7 @@ <translation id="7052633198403197513">F1 鍵</translation> <translation id="2052389551707911401"><ph name="NUMBER_MANY"/> 小時</translation> <translation id="8677655579646609597"><ph name="QUANTITY"/> KB/秒</translation> +<translation id="8394908167088220973">媒體播放/暫停</translation> <translation id="2148716181193084225">今天</translation> <translation id="7960078400008666149">1 小時內請勿打擾</translation> <translation id="4373894838514502496"><ph name="NUMBER_FEW"/> 分鐘前</translation> @@ -114,14 +116,15 @@ <translation id="8447116497070723931">PgUp</translation> <translation id="4588090240171750605">向右捲動</translation> <translation id="7414887922320653780">剩下 <ph name="NUMBER_ONE"/> 小時</translation> +<translation id="1413622004203049571">停用「<ph name="NOTIFIER_NAME"/>」的通知</translation> <translation id="2666092431469916601">置頂</translation> <translation id="8331626408530291785">向上捲動</translation> -<translation id="4773379706300191099">停用 <ph name="EXTENSION_NAME"/> 的通知</translation> <translation id="7907591526440419938">開啟檔案</translation> <translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation> <translation id="1293699935367580298">Esc</translation> <translation id="2797524280730715045"><ph name="NUMBER_DEFAULT"/> 小時前</translation> <translation id="815598010540052116">向下捲動</translation> +<translation id="6808150112686056157">停止媒體播放</translation> <translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation> <translation id="3157931365184549694">還原</translation> <translation id="1243314992276662751">上傳</translation> @@ -159,6 +162,7 @@ <translation id="1101671447232096497"><ph name="NUMBER_MANY"/> 分鐘前</translation> <translation id="6142413573757616983"><ph name="QUANTITY"/> B/秒</translation> <translation id="7649070708921625228">說明</translation> +<translation id="6699343763173986273">下一首媒體曲目</translation> <translation id="8226233771743600312">1 天內請勿打擾</translation> <translation id="7457942297256758195">全部清除</translation> <translation id="822618367988303761"><ph name="NUMBER_TWO"/> 天前</translation> @@ -178,7 +182,6 @@ <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation> <translation id="5941711191222866238">縮到最小</translation> <translation id="6394627529324717982">逗號</translation> -<translation id="4469842253116033348">停用 <ph name="SITE"/> 的通知</translation> <translation id="3036649622769666520">開啟檔案</translation> <translation id="8328145009876646418">左邊緣</translation> <translation id="7372005818821648611"><ph name="NUMBER_TWO"/> 秒</translation> diff --git a/chromium/ui/base/theme_provider.h b/chromium/ui/base/theme_provider.h index 22f70a0025c..d12e2656235 100644 --- a/chromium/ui/base/theme_provider.h +++ b/chromium/ui/base/theme_provider.h @@ -59,7 +59,7 @@ class UI_EXPORT ThemeProvider { // Get the property (e.g. an alignment expressed in an enum, or a width or // height) specified by |id|. - virtual bool GetDisplayProperty(int id, int* result) const = 0; + virtual int GetDisplayProperty(int id) const = 0; // Whether we should use the native system frame (typically Aero glass) or // a custom frame. diff --git a/chromium/ui/base/touch/touch_factory_x11.cc b/chromium/ui/base/touch/touch_factory_x11.cc index 79619f368f5..21fa6a2c7e4 100644 --- a/chromium/ui/base/touch/touch_factory_x11.cc +++ b/chromium/ui/base/touch/touch_factory_x11.cc @@ -19,7 +19,7 @@ #include "base/strings/string_split.h" #include "ui/base/ui_base_switches.h" #include "ui/base/x/device_list_cache_x.h" -#include "ui/base/x/x11_util.h" +#include "ui/gfx/x/x11_types.h" namespace ui { @@ -29,7 +29,7 @@ TouchFactory::TouchFactory() touch_events_disabled_(false), touch_device_list_(), #if defined(USE_XI2_MT) - min_available_slot_(0), + id_generator_(0), #endif slots_used_() { #if defined(USE_AURA) @@ -37,7 +37,7 @@ TouchFactory::TouchFactory() return; #endif - Display* display = GetXDisplay(); + XDisplay* display = gfx::GetXDisplay(); UpdateDeviceList(display); CommandLine* cmdline = CommandLine::ForCurrentProcess(); @@ -177,7 +177,7 @@ void TouchFactory::SetupXI2ForXWindow(Window window) { // the events from uninteresting devices. We do the latter because that's // simpler. - Display* display = ui::GetXDisplay(); + XDisplay* display = gfx::GetXDisplay(); unsigned char mask[XIMaskLen(XI_LASTEVENT)]; memset(mask, 0, sizeof(mask)); @@ -225,46 +225,18 @@ bool TouchFactory::IsMultiTouchDevice(unsigned int deviceid) const { #if defined(USE_XI2_MT) bool TouchFactory::QuerySlotForTrackingID(uint32 tracking_id, int* slot) { - TrackingIdMap::iterator itr = tracking_id_map_.find(tracking_id); - if (itr != tracking_id_map_.end()) { - *slot = itr->second; - return true; - } - return false; + if (!id_generator_.HasGeneratedIDFor(tracking_id)) + return false; + *slot = static_cast<int>(id_generator_.GetGeneratedID(tracking_id)); + return true; } int TouchFactory::GetSlotForTrackingID(uint32 tracking_id) { - TrackingIdMap::iterator itr = tracking_id_map_.find(tracking_id); - if (itr != tracking_id_map_.end()) - return itr->second; - - int slot = min_available_slot_; - if (slot == kMaxTouchPoints) { - LOG(ERROR) << "Could not find available slot for touch point"; - return 0; - } - SetSlotUsed(slot, true); - tracking_id_map_.insert(std::make_pair(tracking_id, slot)); - - // Updates the minium available slot ID - while (++min_available_slot_ < kMaxTouchPoints && - IsSlotUsed(min_available_slot_)) - continue; - - return slot; + return id_generator_.GetGeneratedID(tracking_id); } void TouchFactory::ReleaseSlotForTrackingID(uint32 tracking_id) { - TrackingIdMap::iterator itr = tracking_id_map_.find(tracking_id); - if (itr != tracking_id_map_.end()) { - int slot = itr->second; - SetSlotUsed(slot, false); - tracking_id_map_.erase(itr); - if (slot < min_available_slot_) - min_available_slot_ = slot; - } else { - NOTREACHED() << "Cannot find slot mapping to tracking ID " << tracking_id; - } + id_generator_.ReleaseNumber(tracking_id); } #endif diff --git a/chromium/ui/base/touch/touch_factory_x11.h b/chromium/ui/base/touch/touch_factory_x11.h index a6e8e296581..fbbf9633f1e 100644 --- a/chromium/ui/base/touch/touch_factory_x11.h +++ b/chromium/ui/base/touch/touch_factory_x11.h @@ -9,8 +9,8 @@ #include <map> #include <vector> -#include "base/containers/hash_tables.h" #include "base/timer/timer.h" +#include "ui/base/sequential_id_generator.h" #include "ui/base/ui_export.h" template <typename T> struct DefaultSingletonTraits; @@ -122,14 +122,7 @@ class UI_EXPORT TouchFactory { static const int kMaxTouchPoints = 32; #if defined(USE_XI2_MT) - // Stores the minimum available slot ID which helps get slot ID from - // tracking ID. When it equals to kMaxTouchPoints, there is no available - // slot. - int min_available_slot_; - - // A hash table to map tracking ID to slot. - typedef base::hash_map<uint32, int> TrackingIdMap; - TrackingIdMap tracking_id_map_; + SequentialIDGenerator id_generator_; #endif // A lookup table for slots in use for a touch event. diff --git a/chromium/ui/base/ui_base_switches.cc b/chromium/ui/base/ui_base_switches.cc index 7e27ea6348e..ca4586bc217 100644 --- a/chromium/ui/base/ui_base_switches.cc +++ b/chromium/ui/base/ui_base_switches.cc @@ -9,9 +9,6 @@ namespace switches { // Disables use of DWM composition for top level windows. const char kDisableDwmComposition[] = "disable-dwm-composition"; -// Disables the new visual style for application dialogs and controls. -const char kDisableNewDialogStyle[] = "disable-new-dialog-style"; - // Disables touch adjustment. const char kDisableTouchAdjustment[] = "disable-touch-adjustment"; @@ -24,9 +21,6 @@ const char kDisableTouchEditing[] = "disable-touch-editing"; // Disables the Views textfield on Windows. const char kDisableViewsTextfield[] = "disable-views-textfield"; -// Enables the new visual style for application dialogs and controls. -const char kEnableNewDialogStyle[] = "enable-new-dialog-style"; - // Enable scroll prediction for scroll update events. const char kEnableScrollPrediction[] = "enable-scroll-prediction"; @@ -39,12 +33,6 @@ const char kEnableTouchEditing[] = "enable-touch-editing"; // Enables the Views textfield on Windows. const char kEnableViewsTextfield[] = "enable-views-textfield"; -// Enables/Disables High DPI support (windows) -const char kHighDPISupport[] = "high-dpi-support"; - -// Overrides the device scale factor for the browser UI and the contents. -const char kForceDeviceScaleFactor[] = "force-device-scale-factor"; - // If a resource is requested at a scale factor at which it is not available // or the resource is the incorrect size (based on the size of the 1x resource), // generates the missing resource and applies a red mask to the generated diff --git a/chromium/ui/base/ui_base_switches.h b/chromium/ui/base/ui_base_switches.h index 11887d47999..7e4c9a76e9f 100644 --- a/chromium/ui/base/ui_base_switches.h +++ b/chromium/ui/base/ui_base_switches.h @@ -13,18 +13,14 @@ namespace switches { UI_EXPORT extern const char kDisableDwmComposition[]; -UI_EXPORT extern const char kDisableNewDialogStyle[]; UI_EXPORT extern const char kDisableTouchAdjustment[]; UI_EXPORT extern const char kDisableTouchDragDrop[]; UI_EXPORT extern const char kDisableTouchEditing[]; UI_EXPORT extern const char kDisableViewsTextfield[]; -UI_EXPORT extern const char kEnableNewDialogStyle[]; UI_EXPORT extern const char kEnableScrollPrediction[]; UI_EXPORT extern const char kEnableTouchDragDrop[]; UI_EXPORT extern const char kEnableTouchEditing[]; UI_EXPORT extern const char kEnableViewsTextfield[]; -UI_EXPORT extern const char kForceDeviceScaleFactor[]; -UI_EXPORT extern const char kHighDPISupport[]; UI_EXPORT extern const char kHighlightMissingScaledResources[]; UI_EXPORT extern const char kLang[]; UI_EXPORT extern const char kLocalePak[]; diff --git a/chromium/ui/base/ui_base_switches_util.cc b/chromium/ui/base/ui_base_switches_util.cc index 32034218dd5..3089607af86 100644 --- a/chromium/ui/base/ui_base_switches_util.cc +++ b/chromium/ui/base/ui_base_switches_util.cc @@ -29,13 +29,4 @@ bool IsTouchEditingEnabled() { #endif } -bool IsNewDialogStyleEnabled() { - CommandLine* command_line = CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kDisableNewDialogStyle)) - return false; - if (command_line->HasSwitch(switches::kEnableNewDialogStyle)) - return true; - return true; -} - } // namespace switches diff --git a/chromium/ui/base/ui_base_switches_util.h b/chromium/ui/base/ui_base_switches_util.h index 4c1026124a7..c64da8f6e3c 100644 --- a/chromium/ui/base/ui_base_switches_util.h +++ b/chromium/ui/base/ui_base_switches_util.h @@ -13,8 +13,6 @@ namespace switches { UI_EXPORT bool IsTouchDragDropEnabled(); UI_EXPORT bool IsTouchEditingEnabled(); -UI_EXPORT bool IsNewDialogStyleEnabled(); - } // namespace switches #endif // UI_BASE_UI_BASE_SWITCHES_UTIL_H_ diff --git a/chromium/ui/base/ui_base_types.cc b/chromium/ui/base/ui_base_types.cc index 2d3f812705e..e757edb1e6f 100644 --- a/chromium/ui/base/ui_base_types.cc +++ b/chromium/ui/base/ui_base_types.cc @@ -4,7 +4,7 @@ #include "ui/base/ui_base_types.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" namespace ui { diff --git a/chromium/ui/base/win/events_win.cc b/chromium/ui/base/win/events_win.cc index 6cabff9c22a..04b9cd058aa 100644 --- a/chromium/ui/base/win/events_win.cc +++ b/chromium/ui/base/win/events_win.cc @@ -4,15 +4,15 @@ #include <windowsx.h> -#include "ui/base/events/event_constants.h" +#include "ui/events/event_constants.h" #include "base/logging.h" #include "base/time/time.h" #include "base/win/win_util.h" -#include "ui/base/events/event_utils.h" -#include "ui/base/keycodes/keyboard_code_conversion_win.h" -#include "ui/base/win/dpi.h" +#include "ui/events/event_utils.h" +#include "ui/events/keycodes/keyboard_code_conversion_win.h" #include "ui/gfx/point.h" +#include "ui/gfx/win/dpi.h" namespace ui { @@ -213,7 +213,7 @@ gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) { GET_Y_LPARAM(native_event.lParam) }; ScreenToClient(native_event.hwnd, &native_point); gfx::Point location(native_point); - location = ui::win::ScreenToDIPPoint(location); + location = gfx::win::ScreenToDIPPoint(location); return location; } @@ -357,6 +357,8 @@ int GetModifiersFromKeyState() { modifiers |= EF_CONTROL_DOWN; if (base::win::IsAltPressed()) modifiers |= EF_ALT_DOWN; + if (base::win::IsAltGrPressed()) + modifiers |= EF_ALTGR_DOWN; return modifiers; } diff --git a/chromium/ui/base/win/foreground_helper.cc b/chromium/ui/base/win/foreground_helper.cc index 0b03582a03d..219b26fc1fa 100644 --- a/chromium/ui/base/win/foreground_helper.cc +++ b/chromium/ui/base/win/foreground_helper.cc @@ -5,7 +5,7 @@ #include "ui/base/win/foreground_helper.h" #include "base/logging.h" -#include "ui/base/win/window_impl.h" +#include "ui/gfx/win/window_impl.h" namespace ui { diff --git a/chromium/ui/base/win/foreground_helper.h b/chromium/ui/base/win/foreground_helper.h index 7fc1834dddc..e8101a05b5f 100644 --- a/chromium/ui/base/win/foreground_helper.h +++ b/chromium/ui/base/win/foreground_helper.h @@ -6,7 +6,7 @@ #define UI_BASE_WIN_FOREGROUND_HELPER_H_ #include "base/logging.h" -#include "ui/base/win/window_impl.h" +#include "ui/gfx/win/window_impl.h" namespace ui { @@ -17,7 +17,7 @@ namespace ui { // to be capable of moving to the foreground. // // This is probably leveraging a windows bug. -class UI_EXPORT ForegroundHelper : public WindowImpl { +class UI_EXPORT ForegroundHelper : public gfx::WindowImpl { public: ForegroundHelper() : window_(NULL) { } diff --git a/chromium/ui/base/win/hidden_window.cc b/chromium/ui/base/win/hidden_window.cc index fb4f4836b24..3b21519597c 100644 --- a/chromium/ui/base/win/hidden_window.cc +++ b/chromium/ui/base/win/hidden_window.cc @@ -4,7 +4,7 @@ #include "ui/base/win/hidden_window.h" -#include "ui/base/win/window_impl.h" +#include "ui/gfx/win/window_impl.h" namespace ui { @@ -21,7 +21,7 @@ namespace { // window that interact poorly with us. // // See: http://crbug.com/16476 -class TempParent : public ui::WindowImpl { +class TempParent : public gfx::WindowImpl { public: static TempParent* Get() { static TempParent* g_temp_parent; diff --git a/chromium/ui/base/win/hwnd_subclass.cc b/chromium/ui/base/win/hwnd_subclass.cc index c1133f0543d..34e2bf4fad6 100644 --- a/chromium/ui/base/win/hwnd_subclass.cc +++ b/chromium/ui/base/win/hwnd_subclass.cc @@ -9,8 +9,8 @@ #include "base/logging.h" #include "base/memory/scoped_vector.h" #include "base/memory/singleton.h" -#include "ui/base/win/dpi.h" -#include "ui/base/win/hwnd_util.h" +#include "ui/gfx/win/dpi.h" +#include "ui/gfx/win/hwnd_util.h" namespace { const char kHWNDSubclassKey[] = "__UI_BASE_WIN_HWND_SUBCLASS_PROC__"; @@ -123,7 +123,7 @@ HWNDSubclass::HWNDSubclass(HWND target) : target_(target), original_wnd_proc_(GetCurrentWndProc(target)), prop_(target, kHWNDSubclassKey, this) { - ui::SetWindowProc(target_, &WndProc); + gfx::SetWindowProc(target_, &WndProc); } HWNDSubclass::~HWNDSubclass() { @@ -143,8 +143,10 @@ LRESULT HWNDSubclass::OnWndProc(HWND hwnd, if (GetTouchInputInfoWrapper(reinterpret_cast<HTOUCHINPUT>(l_param), 1, &point, sizeof(TOUCHINPUT))) { POINT touch_location = { - TOUCH_COORD_TO_PIXEL(point.x) / ui::win::GetUndocumentedDPIScale(), - TOUCH_COORD_TO_PIXEL(point.y) / ui::win::GetUndocumentedDPIScale()}; + TOUCH_COORD_TO_PIXEL(point.x) / + gfx::win::GetUndocumentedDPITouchScale(), + TOUCH_COORD_TO_PIXEL(point.y) / + gfx::win::GetUndocumentedDPITouchScale()}; HWND actual_target = WindowFromPoint(touch_location); if (actual_target != hwnd) { return SendMessage(actual_target, message, w_param, l_param); diff --git a/chromium/ui/base/win/hwnd_subclass_unittest.cc b/chromium/ui/base/win/hwnd_subclass_unittest.cc index 5917ef2c101..520f52b4b16 100644 --- a/chromium/ui/base/win/hwnd_subclass_unittest.cc +++ b/chromium/ui/base/win/hwnd_subclass_unittest.cc @@ -6,13 +6,13 @@ #include "base/basictypes.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/win/window_impl.h" +#include "ui/gfx/win/window_impl.h" namespace ui { namespace { -class TestWindow : public ui::WindowImpl { +class TestWindow : public gfx::WindowImpl { public: TestWindow() : saw_message(false) {} virtual ~TestWindow() {} @@ -20,7 +20,7 @@ class TestWindow : public ui::WindowImpl { bool saw_message; private: - // Overridden from ui::WindowImpl: + // Overridden from gfx::WindowImpl: virtual BOOL ProcessWindowMessage(HWND window, UINT message, WPARAM w_param, diff --git a/chromium/ui/base/win/mouse_wheel_util.cc b/chromium/ui/base/win/mouse_wheel_util.cc index 941c069e005..223e3a8ee50 100644 --- a/chromium/ui/base/win/mouse_wheel_util.cc +++ b/chromium/ui/base/win/mouse_wheel_util.cc @@ -8,7 +8,7 @@ #include "base/auto_reset.h" #include "ui/base/view_prop.h" -#include "ui/base/win/hwnd_util.h" +#include "ui/gfx/win/hwnd_util.h" namespace ui { @@ -31,7 +31,7 @@ static bool WindowSupportsRerouteMouseWheel(HWND window) { } static bool IsCompatibleWithMouseWheelRedirection(HWND window) { - std::wstring class_name = GetClassName(window); + std::wstring class_name = gfx::GetClassName(window); // Mousewheel redirection to comboboxes is a surprising and // undesireable user behavior. return !(class_name == L"ComboBox" || @@ -39,7 +39,7 @@ static bool IsCompatibleWithMouseWheelRedirection(HWND window) { } static bool CanRedirectMouseWheelFrom(HWND window) { - std::wstring class_name = GetClassName(window); + std::wstring class_name = gfx::GetClassName(window); // Older Thinkpad mouse wheel drivers create a window under mouse wheel // pointer. Detect if we are dealing with this window. In this case we diff --git a/chromium/ui/base/win/shell.cc b/chromium/ui/base/win/shell.cc index df90108ac4f..0f955375e52 100644 --- a/chromium/ui/base/win/shell.cc +++ b/chromium/ui/base/win/shell.cc @@ -98,6 +98,22 @@ bool OpenItemViaShellNoZoneCheck(const base::FilePath& full_path) { SEE_MASK_NOZONECHECKS | SEE_MASK_FLAG_DDEWAIT); } +bool PreventWindowFromPinning(HWND hwnd) { + // This functionality is only available on Win7+. It also doesn't make sense + // to do this for Chrome Metro. + if (base::win::GetVersion() < base::win::VERSION_WIN7 || + base::win::IsMetroProcess()) + return false; + base::win::ScopedComPtr<IPropertyStore> pps; + HRESULT result = SHGetPropertyStoreForWindow( + hwnd, __uuidof(*pps), reinterpret_cast<void**>(pps.Receive())); + if (FAILED(result)) + return false; + + return base::win::SetBooleanValueForPropertyStore( + pps, PKEY_AppUserModel_PreventPinning, true); +} + void SetAppIdForWindow(const string16& app_id, HWND hwnd) { SetAppDetailsForWindow(app_id, string16(), string16(), string16(), hwnd); } diff --git a/chromium/ui/base/win/shell.h b/chromium/ui/base/win/shell.h index 364b7a32712..31dbb889c2c 100644 --- a/chromium/ui/base/win/shell.h +++ b/chromium/ui/base/win/shell.h @@ -41,6 +41,11 @@ UI_EXPORT bool OpenAnyViaShell(const string16& full_path, // Returns 'true' on successful open, 'false' otherwise. bool OpenItemWithExternalApp(const string16& full_path); +// Disables the ability of the specified window to be pinned to the taskbar or +// the Start menu. This will remove "Pin this program to taskbar" from the +// taskbar menu of the specified window. +UI_EXPORT bool PreventWindowFromPinning(HWND hwnd); + // Sets the application id given as the Application Model ID for the window // specified. This method is used to insure that different web applications // do not group together on the Win7 task bar. diff --git a/chromium/ui/base/window_open_disposition.cc b/chromium/ui/base/window_open_disposition.cc index 5e27bcc209a..c0d131f4bfc 100644 --- a/chromium/ui/base/window_open_disposition.cc +++ b/chromium/ui/base/window_open_disposition.cc @@ -5,7 +5,7 @@ #include "ui/base/window_open_disposition.h" #include "build/build_config.h" -#include "ui/base/events/event_constants.h" +#include "ui/events/event_constants.h" namespace ui { diff --git a/chromium/ui/base/x/active_window_watcher_x.cc b/chromium/ui/base/x/active_window_watcher_x.cc index a277ccde2c5..9d3e791fd53 100644 --- a/chromium/ui/base/x/active_window_watcher_x.cc +++ b/chromium/ui/base/x/active_window_watcher_x.cc @@ -8,11 +8,11 @@ #include <gdk/gdkx.h> #include "base/memory/singleton.h" -#include "ui/base/gtk/gdk_x_compat.h" -#include "ui/base/gtk/gtk_compat.h" #include "ui/base/x/active_window_watcher_x_observer.h" #include "ui/base/x/root_window_property_watcher_x.h" #include "ui/base/x/x11_util.h" +#include "ui/gfx/gdk_compat.h" +#include "ui/gfx/gtk_compat.h" namespace ui { diff --git a/chromium/ui/base/x/device_data_manager.cc b/chromium/ui/base/x/device_data_manager.cc index 3dbd79dccba..784819f6b08 100644 --- a/chromium/ui/base/x/device_data_manager.cc +++ b/chromium/ui/base/x/device_data_manager.cc @@ -10,12 +10,11 @@ #include "base/logging.h" #include "base/memory/singleton.h" -#include "base/message_loop/message_pump_aurax11.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/events/event_utils.h" #include "ui/base/touch/touch_factory_x11.h" #include "ui/base/x/device_list_cache_x.h" #include "ui/base/x/x11_util.h" +#include "ui/events/event_constants.h" +#include "ui/events/event_utils.h" // XIScrollClass was introduced in XI 2.1 so we need to define it here // for backward-compatibility with older versions of XInput. @@ -117,12 +116,12 @@ DeviceDataManager* DeviceDataManager::GetInstance() { DeviceDataManager::DeviceDataManager() : natural_scroll_enabled_(false), - atom_cache_(ui::GetXDisplay(), kCachedAtoms) { + atom_cache_(gfx::GetXDisplay(), kCachedAtoms) { InitializeXInputInternal(); // Make sure the sizes of enum and kCachedAtoms are aligned. CHECK(arraysize(kCachedAtoms) == static_cast<size_t>(DT_LAST_ENTRY) + 1); - UpdateDeviceList(ui::GetXDisplay()); + UpdateDeviceList(gfx::GetXDisplay()); } DeviceDataManager::~DeviceDataManager() { @@ -133,7 +132,7 @@ bool DeviceDataManager::InitializeXInputInternal() { xi_opcode_ = -1; int opcode, event, error; if (!XQueryExtension( - ui::GetXDisplay(), "XInputExtension", &opcode, &event, &error)) { + gfx::GetXDisplay(), "XInputExtension", &opcode, &event, &error)) { VLOG(1) << "X Input extension not available: error=" << error; return false; } @@ -145,7 +144,7 @@ bool DeviceDataManager::InitializeXInputInternal() { #else int major = 2, minor = 0; #endif - if (XIQueryVersion(ui::GetXDisplay(), &major, &minor) == BadRequest) { + if (XIQueryVersion(gfx::GetXDisplay(), &major, &minor) == BadRequest) { VLOG(1) << "XInput2 not supported in the server."; return false; } diff --git a/chromium/ui/base/x/device_data_manager.h b/chromium/ui/base/x/device_data_manager.h index 82718ab92c3..f07012f51e5 100644 --- a/chromium/ui/base/x/device_data_manager.h +++ b/chromium/ui/base/x/device_data_manager.h @@ -13,9 +13,9 @@ #include "base/basictypes.h" #include "base/event_types.h" -#include "ui/base/events/event_constants.h" #include "ui/base/ui_export.h" #include "ui/base/x/x11_atom_cache.h" +#include "ui/events/event_constants.h" template <typename T> struct DefaultSingletonTraits; diff --git a/chromium/ui/base/x/events_x.cc b/chromium/ui/base/x/events_x.cc index 51521689bf1..06301a9b086 100644 --- a/chromium/ui/base/x/events_x.cc +++ b/chromium/ui/base/x/events_x.cc @@ -2,24 +2,23 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/events/event_constants.h" +#include "ui/events/event_constants.h" #include <string.h> #include <X11/extensions/XInput.h> #include <X11/extensions/XInput2.h> #include <X11/Xlib.h> -#include "base/command_line.h" #include "base/logging.h" #include "base/memory/singleton.h" -#include "base/message_loop/message_pump_aurax11.h" -#include "ui/base/events/event_utils.h" -#include "ui/base/keycodes/keyboard_code_conversion_x.h" +#include "base/message_loop/message_pump_x11.h" #include "ui/base/touch/touch_factory_x11.h" #include "ui/base/x/device_data_manager.h" #include "ui/base/x/device_list_cache_x.h" #include "ui/base/x/x11_atom_cache.h" #include "ui/base/x/x11_util.h" +#include "ui/events/event_utils.h" +#include "ui/events/keycodes/keyboard_code_conversion_x.h" #include "ui/gfx/display.h" #include "ui/gfx/point.h" #include "ui/gfx/rect.h" @@ -33,19 +32,6 @@ const int kWheelScrollAmount = 53; const int kMinWheelButton = 4; const int kMaxWheelButton = 7; -// A workaround for some incorrect implemented input drivers: -// Ignore their mouse input valuators. -bool IgnoreMouseValuators() { - static bool initialized = false; - static bool ignore_valuators = true; - if (initialized) - return ignore_valuators; - ignore_valuators = - CommandLine::ForCurrentProcess()->HasSwitch("disable-mouse-valuators"); - initialized = true; - return ignore_valuators; -} - // A class to track current modifier state on master device. Only track ctrl, // alt, shift and caps lock keys currently. The tracked state can then be used // by floating device. @@ -274,13 +260,7 @@ double GetTouchParamFromXEvent(XEvent* xev, } Atom GetNoopEventAtom() { - return XInternAtom( -#if defined(USE_AURA) - base::MessagePumpAuraX11::GetDefaultXDisplay(), -#else - XOpenDisplay(NULL), -#endif - "noop", False); + return XInternAtom(gfx::GetXDisplay(), "noop", False); } } // namespace @@ -288,7 +268,7 @@ Atom GetNoopEventAtom() { namespace ui { void UpdateDeviceList() { - Display* display = GetXDisplay(); + XDisplay* display = gfx::GetXDisplay(); DeviceListCacheX::GetInstance()->UpdateDeviceList(display); TouchFactory::GetInstance()->UpdateDeviceList(display); DeviceDataManager::GetInstance()->UpdateDeviceList(display); @@ -480,40 +460,8 @@ gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) { case GenericEvent: { XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(native_event->xcookie.data); - -#if defined(USE_XI2_MT) - // Touch event valuators aren't coordinates. - // Return the |event_x|/|event_y| directly as event's position. - if (xievent->evtype == XI_TouchBegin || - xievent->evtype == XI_TouchUpdate || - xievent->evtype == XI_TouchEnd) - // Note: Touch events are always touch screen events. - return gfx::Point(static_cast<int>(xievent->event_x), - static_cast<int>(xievent->event_y)); -#endif - if (IgnoreMouseValuators()) { - return gfx::Point(static_cast<int>(xievent->event_x), - static_cast<int>(xievent->event_y)); - } - // Read the position from the valuators, because the location reported in - // event_x/event_y seems to be different (and doesn't match for events - // coming from slave device and master device) from the values in the - // valuators. See more on crbug.com/103981. The position in the valuators - // is in the global screen coordinates. But it is necessary to convert it - // into the window's coordinates. If the valuator is not set, that means - // the value hasn't changed, and so we can use the value from - // event_x/event_y (which are in the window's coordinates). - double* valuators = xievent->valuators.values; - - double x = xievent->event_x; - if (XIMaskIsSet(xievent->valuators.mask, 0)) - x = *valuators++ - (xievent->root_x - xievent->event_x); - - double y = xievent->event_y; - if (XIMaskIsSet(xievent->valuators.mask, 1)) - y = *valuators++ - (xievent->root_y - xievent->event_y); - - return gfx::Point(static_cast<int>(x), static_cast<int>(y)); + return gfx::Point(static_cast<int>(xievent->event_x), + static_cast<int>(xievent->event_y)); } } return gfx::Point(); diff --git a/chromium/ui/base/x/events_x_unittest.cc b/chromium/ui/base/x/events_x_unittest.cc index 42ed319bac4..3a85a0a0dfa 100644 --- a/chromium/ui/base/x/events_x_unittest.cc +++ b/chromium/ui/base/x/events_x_unittest.cc @@ -12,10 +12,11 @@ #undef None #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/events/event_utils.h" #include "ui/base/touch/touch_factory_x11.h" #include "ui/base/x/device_data_manager.h" +#include "ui/events/event.h" +#include "ui/events/event_constants.h" +#include "ui/events/event_utils.h" #include "ui/gfx/point.h" namespace ui { @@ -234,6 +235,27 @@ TEST(EventsXTest, EnterLeaveEvent) { EXPECT_EQ("230,240", ui::EventSystemLocationFromNative(&event).ToString()); } +TEST(EventsXTest, ClickCount) { + XEvent event; + gfx::Point location(5, 10); + + for (int i = 1; i <= 3; ++i) { + InitButtonEvent(&event, true, location, 1, 0); + { + MouseEvent mouseev(&event); + EXPECT_EQ(ui::ET_MOUSE_PRESSED, mouseev.type()); + EXPECT_EQ(i, mouseev.GetClickCount()); + } + + InitButtonEvent(&event, false, location, 1, 0); + { + MouseEvent mouseev(&event); + EXPECT_EQ(ui::ET_MOUSE_RELEASED, mouseev.type()); + EXPECT_EQ(i, mouseev.GetClickCount()); + } + } +} + #if defined(USE_XI2_MT) TEST(EventsXTest, TouchEventBasic) { std::vector<unsigned int> devices; @@ -248,6 +270,7 @@ TEST(EventsXTest, TouchEventBasic) { valuators.push_back(Valuator(DeviceDataManager::DT_TOUCH_ORIENTATION, 0.3f)); valuators.push_back(Valuator(DeviceDataManager::DT_TOUCH_PRESSURE, 100)); event = CreateTouchEvent(0, XI_TouchBegin, 5, gfx::Point(10, 10), valuators); + EXPECT_EQ(ui::ET_TOUCH_PRESSED, ui::EventTypeFromNative(event)); EXPECT_EQ("10,10", ui::EventLocationFromNative(event).ToString()); EXPECT_EQ(GetTouchId(event), 0); EXPECT_EQ(GetTouchRadiusX(event), 10); @@ -259,6 +282,7 @@ TEST(EventsXTest, TouchEventBasic) { valuators.clear(); valuators.push_back(Valuator(DeviceDataManager::DT_TOUCH_ORIENTATION, 0.5f)); event = CreateTouchEvent(0, XI_TouchUpdate, 5, gfx::Point(20, 20), valuators); + EXPECT_EQ(ui::ET_TOUCH_MOVED, ui::EventTypeFromNative(event)); EXPECT_EQ("20,20", ui::EventLocationFromNative(event).ToString()); EXPECT_EQ(GetTouchId(event), 0); EXPECT_EQ(GetTouchRadiusX(event), 10); @@ -273,6 +297,7 @@ TEST(EventsXTest, TouchEventBasic) { valuators.push_back(Valuator(DeviceDataManager::DT_TOUCH_PRESSURE, 500)); event = CreateTouchEvent( 0, XI_TouchBegin, 6, gfx::Point(200, 200), valuators); + EXPECT_EQ(ui::ET_TOUCH_PRESSED, ui::EventTypeFromNative(event)); EXPECT_EQ("200,200", ui::EventLocationFromNative(event).ToString()); EXPECT_EQ(GetTouchId(event), 1); EXPECT_EQ(GetTouchRadiusX(event), 50); @@ -285,6 +310,7 @@ TEST(EventsXTest, TouchEventBasic) { valuators.clear(); valuators.push_back(Valuator(DeviceDataManager::DT_TOUCH_PRESSURE, 50)); event = CreateTouchEvent(0, XI_TouchEnd, 5, gfx::Point(30, 30), valuators); + EXPECT_EQ(ui::ET_TOUCH_RELEASED, ui::EventTypeFromNative(event)); EXPECT_EQ("30,30", ui::EventLocationFromNative(event).ToString()); EXPECT_EQ(GetTouchId(event), 0); EXPECT_EQ(GetTouchRadiusX(event), 10); @@ -297,6 +323,7 @@ TEST(EventsXTest, TouchEventBasic) { valuators.clear(); valuators.push_back(Valuator(DeviceDataManager::DT_TOUCH_MAJOR, 50)); event = CreateTouchEvent(0, XI_TouchEnd, 6, gfx::Point(200, 200), valuators); + EXPECT_EQ(ui::ET_TOUCH_RELEASED, ui::EventTypeFromNative(event)); EXPECT_EQ("200,200", ui::EventLocationFromNative(event).ToString()); EXPECT_EQ(GetTouchId(event), 1); EXPECT_EQ(GetTouchRadiusX(event), 25); diff --git a/chromium/ui/base/x/selection_requestor.cc b/chromium/ui/base/x/selection_requestor.cc index 405c0592f80..059ea3f1db5 100644 --- a/chromium/ui/base/x/selection_requestor.cc +++ b/chromium/ui/base/x/selection_requestor.cc @@ -4,7 +4,7 @@ #include "ui/base/x/selection_requestor.h" -#include "base/message_loop/message_pump_aurax11.h" +#include "base/message_loop/message_pump_x11.h" #include "base/run_loop.h" #include "ui/base/x/selection_utils.h" #include "ui/base/x/x11_util.h" @@ -56,7 +56,7 @@ bool SelectionRequestor::PerformBlockingConvertSelection( // for a response. base::MessageLoopForUI* loop = base::MessageLoopForUI::current(); base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop); - base::RunLoop run_loop(base::MessagePumpAuraX11::Current()); + base::RunLoop run_loop(base::MessagePumpX11::Current()); current_target_ = target; in_nested_loop_ = true; diff --git a/chromium/ui/base/x/selection_utils.cc b/chromium/ui/base/x/selection_utils.cc index 4696b0047ad..e0f1d9b5e0c 100644 --- a/chromium/ui/base/x/selection_utils.cc +++ b/chromium/ui/base/x/selection_utils.cc @@ -104,6 +104,7 @@ SelectionFormatMap::~SelectionFormatMap() {} void SelectionFormatMap::Insert( ::Atom atom, const scoped_refptr<base::RefCountedMemory>& item) { + data_.erase(atom); data_.insert(std::make_pair(atom, item)); } @@ -132,7 +133,7 @@ std::vector< ::Atom> SelectionFormatMap::GetTypes() const { SelectionData::SelectionData() : type_(None), - atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) { + atom_cache_(gfx::GetXDisplay(), kSelectionDataAtoms) { } SelectionData::SelectionData( @@ -140,13 +141,13 @@ SelectionData::SelectionData( const scoped_refptr<base::RefCountedMemory>& memory) : type_(type), memory_(memory), - atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) { + atom_cache_(gfx::GetXDisplay(), kSelectionDataAtoms) { } SelectionData::SelectionData(const SelectionData& rhs) : type_(rhs.type_), memory_(rhs.memory_), - atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) { + atom_cache_(gfx::GetXDisplay(), kSelectionDataAtoms) { } SelectionData::~SelectionData() {} diff --git a/chromium/ui/base/x/x11_atom_cache.cc b/chromium/ui/base/x/x11_atom_cache.cc index 1c49ddb2a4b..09e59f1ace8 100644 --- a/chromium/ui/base/x/x11_atom_cache.cc +++ b/chromium/ui/base/x/x11_atom_cache.cc @@ -6,8 +6,8 @@ #include <X11/Xatom.h> +#include "base/logging.h" #include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_pump_aurax11.h" namespace ui { diff --git a/chromium/ui/base/x/x11_error_tracker.cc b/chromium/ui/base/x/x11_error_tracker.cc new file mode 100644 index 00000000000..22bc798321b --- /dev/null +++ b/chromium/ui/base/x/x11_error_tracker.cc @@ -0,0 +1,37 @@ +// Copyright (c) 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 "ui/base/x/x11_error_tracker.h" + +#include "ui/base/x/x11_util.h" + +namespace { + +unsigned char g_x11_error_code = 0; + +int X11ErrorHandler(XDisplay* display, XErrorEvent* error) { + g_x11_error_code = error->error_code; + return 0; +} + +} + +namespace ui { + +X11ErrorTracker::X11ErrorTracker() { + old_handler_ = XSetErrorHandler(X11ErrorHandler); +} + +X11ErrorTracker::~X11ErrorTracker() { + XSetErrorHandler(old_handler_); +} + +bool X11ErrorTracker::FoundNewError() { + XSync(gfx::GetXDisplay(), False); + unsigned char error = g_x11_error_code; + g_x11_error_code = 0; + return error != 0; +} + +} // namespace ui diff --git a/chromium/ui/base/x/x11_error_tracker.h b/chromium/ui/base/x/x11_error_tracker.h new file mode 100644 index 00000000000..57d46d1b3ac --- /dev/null +++ b/chromium/ui/base/x/x11_error_tracker.h @@ -0,0 +1,33 @@ +// Copyright (c) 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 <X11/Xlib.h> + +#include "base/basictypes.h" +#include "ui/base/ui_export.h" + +namespace ui { + +// X11ErrorTracker catches X11 errors in a non-fatal way. It does so by +// temporarily changing the X11 error handler. The old error handler is +// restored when the tracker is destroyed. +class UI_EXPORT X11ErrorTracker { + public: + X11ErrorTracker(); + ~X11ErrorTracker(); + + // Returns whether an X11 error happened since this function was last called + // (or since the creation of the tracker). This is potentially expensive, + // since this causes a sync with the X server. + bool FoundNewError(); + + private: +#if !defined(TOOLKIT_GTK) + XErrorHandler old_handler_; +#endif + + DISALLOW_COPY_AND_ASSIGN(X11ErrorTracker); +}; + +} // namespace ui diff --git a/chromium/ui/base/x/x11_error_tracker_gtk.cc b/chromium/ui/base/x/x11_error_tracker_gtk.cc new file mode 100644 index 00000000000..2806d34b978 --- /dev/null +++ b/chromium/ui/base/x/x11_error_tracker_gtk.cc @@ -0,0 +1,29 @@ +// Copyright (c) 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 "ui/base/x/x11_error_tracker.h" + +#include <gdk/gdkx.h> + +#include "base/logging.h" + +namespace ui { + +X11ErrorTracker::X11ErrorTracker() { + gdk_error_trap_push(); +} + +X11ErrorTracker::~X11ErrorTracker() { + gdk_error_trap_pop(); +} + +bool X11ErrorTracker::FoundNewError() { + gdk_flush(); + bool found_error = gdk_error_trap_pop() != 0; + + gdk_error_trap_push(); + return found_error; +} + +} // namespace ui diff --git a/chromium/ui/base/x/x11_util.cc b/chromium/ui/base/x/x11_util.cc index 836feae8e50..58c2c698a3c 100644 --- a/chromium/ui/base/x/x11_util.cc +++ b/chromium/ui/base/x/x11_util.cc @@ -32,11 +32,18 @@ #include "base/strings/stringprintf.h" #include "base/sys_byteorder.h" #include "base/threading/thread.h" -#include "ui/base/events/event_utils.h" -#include "ui/base/keycodes/keyboard_code_conversion_x.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/skia/include/core/SkPostConfig.h" #include "ui/base/touch/touch_factory_x11.h" #include "ui/base/x/device_data_manager.h" +#include "ui/base/x/x11_error_tracker.h" #include "ui/base/x/x11_util_internal.h" +#include "ui/events/event_utils.h" +#include "ui/events/keycodes/keyboard_code_conversion_x.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/image/image_skia.h" +#include "ui/gfx/image/image_skia_rep.h" +#include "ui/gfx/point.h" #include "ui/gfx/point_conversions.h" #include "ui/gfx/rect.h" #include "ui/gfx/size.h" @@ -49,22 +56,14 @@ #if defined(USE_AURA) #include <X11/Xcursor/Xcursor.h> #include "skia/ext/image_operations.h" -#include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/skia_util.h" #endif #if defined(TOOLKIT_GTK) #include <gdk/gdk.h> -#include <gdk/gdkx.h> #include <gtk/gtk.h> -#include "ui/base/gtk/gdk_x_compat.h" -#include "ui/base/gtk/gtk_compat.h" -#else -// TODO(sad): Use the new way of handling X errors when -// http://codereview.chromium.org/7889040/ lands. -#define gdk_error_trap_push() -#define gdk_error_trap_pop() false -#define gdk_flush() +#include "ui/gfx/gdk_compat.h" +#include "ui/gfx/gtk_compat.h" #endif namespace ui { @@ -73,11 +72,11 @@ namespace { // Used to cache the XRenderPictFormat for a visual/display pair. struct CachedPictFormat { - bool equals(Display* display, Visual* visual) const { + bool equals(XDisplay* display, Visual* visual) const { return display == this->display && visual == this->visual; } - Display* display; + XDisplay* display; Visual* visual; XRenderPictFormat* format; }; @@ -95,7 +94,7 @@ CachedPictFormats* get_cached_pict_formats() { // Maximum number of CachedPictFormats we keep around. const size_t kMaxCacheSize = 5; -int DefaultX11ErrorHandler(Display* d, XErrorEvent* e) { +int DefaultX11ErrorHandler(XDisplay* d, XErrorEvent* e) { if (base::MessageLoop::current()) { base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind(&LogErrorEventDescription, d, *e)); @@ -110,7 +109,7 @@ int DefaultX11ErrorHandler(Display* d, XErrorEvent* e) { return 0; } -int DefaultX11IOErrorHandler(Display* d) { +int DefaultX11IOErrorHandler(XDisplay* d) { // If there's an IO error it likely means the X server has gone away LOG(ERROR) << "X IO error received (X server probably went away)"; _exit(1); @@ -122,7 +121,7 @@ bool GetProperty(XID window, const std::string& property_name, long max_length, unsigned char** property) { Atom property_atom = GetAtom(property_name.c_str()); unsigned long remaining_bytes = 0; - return XGetWindowProperty(GetXDisplay(), + return XGetWindowProperty(gfx::GetXDisplay(), window, property_atom, 0, // offset into property data to read @@ -160,7 +159,7 @@ int XKeyEventType(ui::EventType type) { // Converts KeyboardCode to XKeyEvent keycode. unsigned int XKeyEventKeyCode(ui::KeyboardCode key_code, int flags, - Display* display) { + XDisplay* display) { const int keysym = XKeysymForWindowsKeyCode(key_code, flags & ui::EF_SHIFT_DOWN); // Tests assume the keycode for XK_less is equal to the one of XK_comma, @@ -183,14 +182,14 @@ class XCursorCache { std::pair<std::map<int, ::Cursor>::iterator, bool> it = cache_.insert( std::make_pair(cursor_shape, 0)); if (it.second) { - Display* display = base::MessagePumpForUI::GetDefaultXDisplay(); + XDisplay* display = base::MessagePumpForUI::GetDefaultXDisplay(); it.first->second = XCreateFontCursor(display, cursor_shape); } return it.first->second; } void Clear() { - Display* display = base::MessagePumpForUI::GetDefaultXDisplay(); + XDisplay* display = base::MessagePumpForUI::GetDefaultXDisplay(); for (std::map<int, ::Cursor>::iterator it = cache_.begin(); it != cache_.end(); ++it) { XFreeCursor(display, it->second); @@ -244,12 +243,12 @@ class XCustomCursorCache { XCustomCursor(XcursorImage* image) : image_(image), ref_(1) { - cursor_ = XcursorImageLoadCursor(GetXDisplay(), image); + cursor_ = XcursorImageLoadCursor(gfx::GetXDisplay(), image); } ~XCustomCursor() { XcursorImageDestroy(image_); - XFreeCursor(GetXDisplay(), cursor_); + XFreeCursor(gfx::GetXDisplay(), cursor_); } ::Cursor cursor() const { return cursor_; } @@ -293,7 +292,7 @@ class XButtonMap { } void UpdateMapping() { - count_ = XGetPointerMapping(ui::GetXDisplay(), map_, arraysize(map_)); + count_ = XGetPointerMapping(gfx::GetXDisplay(), map_, arraysize(map_)); } int GetMappedButton(int button) { @@ -318,7 +317,7 @@ class XButtonMap { bool IsShapeAvailable() { int dummy; static bool is_shape_available = - XShapeQueryExtension(ui::GetXDisplay(), &dummy, &dummy); + XShapeQueryExtension(gfx::GetXDisplay(), &dummy, &dummy); return is_shape_available; } @@ -326,14 +325,10 @@ bool IsShapeAvailable() { } // namespace bool XDisplayExists() { - return (GetXDisplay() != NULL); + return (gfx::GetXDisplay() != NULL); } -Display* GetXDisplay() { - return base::MessagePumpForUI::GetDefaultXDisplay(); -} - -static SharedMemorySupport DoQuerySharedMemorySupport(Display* dpy) { +static SharedMemorySupport DoQuerySharedMemorySupport(XDisplay* dpy) { int dummy; Bool pixmaps_supported; // Query the server's support for XSHM. @@ -370,14 +365,13 @@ static SharedMemorySupport DoQuerySharedMemorySupport(Display* dpy) { memset(&shminfo, 0, sizeof(shminfo)); shminfo.shmid = shmkey; - gdk_error_trap_push(); + X11ErrorTracker err_tracker; bool result = XShmAttach(dpy, &shminfo); if (result) VLOG(1) << "X got shared memory segment " << shmkey; else LOG(WARNING) << "X failed to attach to shared memory segment " << shmkey; - XSync(dpy, False); - if (gdk_error_trap_pop()) + if (err_tracker.FoundNewError()) result = false; shmdt(address); if (!result) { @@ -391,7 +385,7 @@ static SharedMemorySupport DoQuerySharedMemorySupport(Display* dpy) { return pixmaps_supported ? SHARED_MEMORY_PIXMAP : SHARED_MEMORY_PUTIMAGE; } -SharedMemorySupport QuerySharedMemorySupport(Display* dpy) { +SharedMemorySupport QuerySharedMemorySupport(XDisplay* dpy) { static SharedMemorySupport shared_memory_support = SHARED_MEMORY_NONE; static bool shared_memory_support_cached = false; @@ -404,7 +398,7 @@ SharedMemorySupport QuerySharedMemorySupport(Display* dpy) { return shared_memory_support; } -bool QueryRenderSupport(Display* dpy) { +bool QueryRenderSupport(XDisplay* dpy) { static bool render_supported = false; static bool render_supported_cached = false; @@ -420,7 +414,7 @@ bool QueryRenderSupport(Display* dpy) { return render_supported; } -int GetDefaultScreen(Display* display) { +int GetDefaultScreen(XDisplay* display) { return XDefaultScreen(display); } @@ -495,7 +489,7 @@ int CoalescePendingMotionEvents(const XEvent* xev, XEvent* last_event) { XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); int num_coalesced = 0; - Display* display = xev->xany.display; + XDisplay* display = xev->xany.display; int event_type = xev->xgeneric.evtype; DCHECK_EQ(event_type, XI_Motion); @@ -565,13 +559,13 @@ int CoalescePendingMotionEvents(const XEvent* xev, void HideHostCursor() { CR_DEFINE_STATIC_LOCAL(XScopedCursor, invisible_cursor, - (CreateInvisibleCursor(), ui::GetXDisplay())); - XDefineCursor(ui::GetXDisplay(), DefaultRootWindow(ui::GetXDisplay()), + (CreateInvisibleCursor(), gfx::GetXDisplay())); + XDefineCursor(gfx::GetXDisplay(), DefaultRootWindow(gfx::GetXDisplay()), invisible_cursor.get()); } ::Cursor CreateInvisibleCursor() { - Display* xdisplay = ui::GetXDisplay(); + XDisplay* xdisplay = gfx::GetXDisplay(); ::Cursor invisible_cursor; char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; XColor black; @@ -586,7 +580,7 @@ void HideHostCursor() { } XID GetX11RootWindow() { - return DefaultRootWindow(GetXDisplay()); + return DefaultRootWindow(gfx::GetXDisplay()); } bool GetCurrentDesktop(int* desktop) { @@ -623,7 +617,7 @@ void* GetVisualFromGtkWidget(GtkWidget* widget) { void SetHideTitlebarWhenMaximizedProperty(XID window, HideTitlebarWhenMaximized property) { uint32 hide = property; - XChangeProperty(GetXDisplay(), + XChangeProperty(gfx::GetXDisplay(), window, GetAtom("_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"), XA_CARDINAL, @@ -634,7 +628,7 @@ void SetHideTitlebarWhenMaximizedProperty(XID window, } void ClearX11DefaultRootWindow() { - Display* display = GetXDisplay(); + XDisplay* display = gfx::GetXDisplay(); XID root_window = GetX11RootWindow(); gfx::Rect root_bounds; if (!GetWindowRect(root_window, &root_bounds)) { @@ -653,7 +647,7 @@ void ClearX11DefaultRootWindow() { XFreeGC(display, gc); } -int BitsPerPixelForPixmapDepth(Display* dpy, int depth) { +int BitsPerPixelForPixmapDepth(XDisplay* dpy, int depth) { int count; XPixmapFormatValues* formats = XListPixmapFormats(dpy, &count); if (!formats) @@ -673,7 +667,7 @@ int BitsPerPixelForPixmapDepth(Display* dpy, int depth) { bool IsWindowVisible(XID window) { XWindowAttributes win_attributes; - if (!XGetWindowAttributes(GetXDisplay(), window, &win_attributes)) + if (!XGetWindowAttributes(gfx::GetXDisplay(), window, &win_attributes)) return false; if (win_attributes.map_state != IsViewable) return false; @@ -692,11 +686,11 @@ bool GetWindowRect(XID window, gfx::Rect* rect) { unsigned int width, height; unsigned int border_width, depth; - if (!XGetGeometry(GetXDisplay(), window, &root, &x, &y, + if (!XGetGeometry(gfx::GetXDisplay(), window, &root, &x, &y, &width, &height, &border_width, &depth)) return false; - if (!XTranslateCoordinates(GetXDisplay(), window, root, + if (!XTranslateCoordinates(gfx::GetXDisplay(), window, root, 0, 0, &x, &y, &child)) return false; @@ -725,7 +719,7 @@ bool WindowContainsPoint(XID window, gfx::Point screen_loc) { int dummy; int input_rects_size = 0; XRectangle* input_rects = XShapeGetRectangles( - ui::GetXDisplay(), window, ShapeInput, &input_rects_size, &dummy); + gfx::GetXDisplay(), window, ShapeInput, &input_rects_size, &dummy); if (!input_rects) return true; bool is_in_input_rects = false; @@ -773,7 +767,7 @@ bool GetRawBytesOfProperty(XID window, Atom prop_type = None; int prop_format = 0; unsigned char* property_data = NULL; - if (XGetWindowProperty(GetXDisplay(), window, property, + if (XGetWindowProperty(gfx::GetXDisplay(), window, property, 0, 0x1FFFFFFF /* MAXINT32 / 4 */, False, AnyPropertyType, &prop_type, &prop_format, &nitems, &nbytes, &property_data) != Success) { @@ -958,8 +952,8 @@ bool SetIntArrayProperty(XID window, for (size_t i = 0; i < value.size(); ++i) data[i] = value[i]; - gdk_error_trap_push(); - XChangeProperty(ui::GetXDisplay(), + X11ErrorTracker err_tracker; + XChangeProperty(gfx::GetXDisplay(), window, name_atom, type_atom, @@ -967,8 +961,7 @@ bool SetIntArrayProperty(XID window, PropModeReplace, reinterpret_cast<const unsigned char*>(data.get()), value.size()); // num items - XSync(ui::GetXDisplay(), False); - return gdk_error_trap_pop() == 0; + return !err_tracker.FoundNewError(); } bool SetAtomArrayProperty(XID window, @@ -984,8 +977,8 @@ bool SetAtomArrayProperty(XID window, for (size_t i = 0; i < value.size(); ++i) data[i] = value[i]; - gdk_error_trap_push(); - XChangeProperty(ui::GetXDisplay(), + X11ErrorTracker err_tracker; + XChangeProperty(gfx::GetXDisplay(), window, name_atom, type_atom, @@ -993,8 +986,7 @@ bool SetAtomArrayProperty(XID window, PropModeReplace, reinterpret_cast<const unsigned char*>(data.get()), value.size()); // num items - XSync(ui::GetXDisplay(), False); - return gdk_error_trap_pop() == 0; + return !err_tracker.FoundNewError(); } Atom GetAtom(const char* name) { @@ -1003,16 +995,29 @@ Atom GetAtom(const char* name) { gdk_display_get_default(), name); #else // TODO(derat): Cache atoms to avoid round-trips to the server. - return XInternAtom(GetXDisplay(), name, false); + return XInternAtom(gfx::GetXDisplay(), name, false); #endif } +void SetWindowClassHint(XDisplay* display, + XID window, + std::string res_name, + std::string res_class) { + XClassHint class_hints; + // const_cast is safe because XSetClassHint does not modify the strings. + // Just to be safe, the res_name and res_class parameters are local copies, + // not const references. + class_hints.res_name = const_cast<char*>(res_name.c_str()); + class_hints.res_class = const_cast<char*>(res_class.c_str()); + XSetClassHint(display, window, &class_hints); +} + XID GetParentWindow(XID window) { XID root = None; XID parent = None; XID* children = NULL; unsigned int num_children = 0; - XQueryTree(GetXDisplay(), window, &root, &parent, &children, &num_children); + XQueryTree(gfx::GetXDisplay(), window, &root, &parent, &children, &num_children); if (children) XFree(children); return parent; @@ -1033,7 +1038,7 @@ bool GetWindowDesktop(XID window, int* desktop) { return GetIntProperty(window, "_NET_WM_DESKTOP", desktop); } -std::string GetX11ErrorString(Display* display, int err) { +std::string GetX11ErrorString(XDisplay* display, int err) { char buffer[256]; XGetErrorText(display, err, buffer, arraysize(buffer)); return buffer; @@ -1042,7 +1047,7 @@ std::string GetX11ErrorString(Display* display, int err) { // Returns true if |window| is a named window. bool IsWindowNamed(XID window) { XTextProperty prop; - if (!XGetWMName(GetXDisplay(), window, &prop) || !prop.value) + if (!XGetWMName(gfx::GetXDisplay(), window, &prop) || !prop.value) return false; XFree(prop.value); @@ -1056,7 +1061,7 @@ bool EnumerateChildren(EnumerateWindowsDelegate* delegate, XID window, XID root, parent, *children; unsigned int num_children; - int status = XQueryTree(GetXDisplay(), window, &root, &parent, &children, + int status = XQueryTree(gfx::GetXDisplay(), window, &root, &parent, &children, &num_children); if (status == 0) return false; @@ -1148,10 +1153,10 @@ void RestackWindow(XID window, XID sibling, bool above) { XWindowChanges changes; changes.sibling = sibling; changes.stack_mode = above ? Above : Below; - XConfigureWindow(GetXDisplay(), window, CWSibling | CWStackMode, &changes); + XConfigureWindow(gfx::GetXDisplay(), window, CWSibling | CWStackMode, &changes); } -XSharedMemoryId AttachSharedMemory(Display* display, int shared_memory_key) { +XSharedMemoryId AttachSharedMemory(XDisplay* display, int shared_memory_key) { DCHECK(QuerySharedMemorySupport(display)); XShmSegmentInfo shminfo; @@ -1172,7 +1177,7 @@ XSharedMemoryId AttachSharedMemory(Display* display, int shared_memory_key) { return shminfo.shmseg; } -void DetachSharedMemory(Display* display, XSharedMemoryId shmseg) { +void DetachSharedMemory(XDisplay* display, XSharedMemoryId shmseg) { DCHECK(QuerySharedMemorySupport(display)); XShmSegmentInfo shminfo; @@ -1183,14 +1188,63 @@ void DetachSharedMemory(Display* display, XSharedMemoryId shmseg) { NOTREACHED(); } -XID CreatePictureFromSkiaPixmap(Display* display, XID pixmap) { +bool CopyAreaToCanvas(XID drawable, + gfx::Rect source_bounds, + gfx::Point dest_offset, + gfx::Canvas* canvas) { + ui::XScopedImage scoped_image( + XGetImage(gfx::GetXDisplay(), drawable, + source_bounds.x(), source_bounds.y(), + source_bounds.width(), source_bounds.height(), + AllPlanes, ZPixmap)); + XImage* image = scoped_image.get(); + if (!image) { + LOG(ERROR) << "XGetImage failed"; + return false; + } + + if (image->bits_per_pixel == 32) { + if ((0xff << SK_R32_SHIFT) != image->red_mask || + (0xff << SK_G32_SHIFT) != image->green_mask || + (0xff << SK_B32_SHIFT) != image->blue_mask) { + LOG(WARNING) << "XImage and Skia byte orders differ"; + return false; + } + + // Set the alpha channel before copying to the canvas. Otherwise, areas of + // the framebuffer that were cleared by ply-image rather than being obscured + // by an image during boot may end up transparent. + // TODO(derat|marcheu): Remove this if/when ply-image has been updated to + // set the framebuffer's alpha channel regardless of whether the device + // claims to support alpha or not. + for (int i = 0; i < image->width * image->height * 4; i += 4) + image->data[i + 3] = 0xff; + + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, + image->width, image->height, + image->bytes_per_line); + bitmap.setPixels(image->data); + gfx::ImageSkia image_skia; + gfx::ImageSkiaRep image_rep(bitmap, canvas->scale_factor()); + image_skia.AddRepresentation(image_rep); + canvas->DrawImageInt(image_skia, dest_offset.x(), dest_offset.y()); + } else { + NOTIMPLEMENTED() << "Unsupported bits-per-pixel " << image->bits_per_pixel; + return false; + } + + return true; +} + +XID CreatePictureFromSkiaPixmap(XDisplay* display, XID pixmap) { XID picture = XRenderCreatePicture( display, pixmap, GetRenderARGB32Format(display), 0, NULL); return picture; } -void PutARGBImage(Display* display, +void PutARGBImage(XDisplay* display, void* visual, int depth, XID pixmap, void* pixmap_gc, const uint8* data, @@ -1204,7 +1258,7 @@ void PutARGBImage(Display* display, width, height); } -void PutARGBImage(Display* display, +void PutARGBImage(XDisplay* display, void* visual, int depth, XID pixmap, void* pixmap_gc, const uint8* data, @@ -1309,11 +1363,11 @@ void PutARGBImage(Display* display, } } -void FreePicture(Display* display, XID picture) { +void FreePicture(XDisplay* display, XID picture) { XRenderFreePicture(display, picture); } -void FreePixmap(Display* display, XID pixmap) { +void FreePixmap(XDisplay* display, XID pixmap) { XFreePixmap(display, pixmap); } @@ -1335,21 +1389,18 @@ bool GetWindowManagerName(std::string* wm_name) { // _NET_SUPPORTING_WM_CHECK property pointing to itself (to avoid a stale // property referencing an ID that's been recycled for another window), so we // check that too. - gdk_error_trap_push(); + X11ErrorTracker err_tracker; int wm_window_property = 0; bool result = GetIntProperty( wm_window, "_NET_SUPPORTING_WM_CHECK", &wm_window_property); - gdk_flush(); - bool got_error = gdk_error_trap_pop(); - if (got_error || !result || wm_window_property != wm_window) + if (err_tracker.FoundNewError() || !result || + wm_window_property != wm_window) { return false; + } - gdk_error_trap_push(); result = GetStringProperty( static_cast<XID>(wm_window), "_NET_WM_NAME", wm_name); - gdk_flush(); - got_error = gdk_error_trap_pop(); - return !got_error && result; + return !err_tracker.FoundNewError() && result; } WindowManagerName GuessWindowManager() { @@ -1402,7 +1453,7 @@ bool ChangeWindowDesktop(XID window, XID destination) { event.xclient.data.l[0] = desktop; event.xclient.data.l[1] = 1; // source indication - int result = XSendEvent(GetXDisplay(), GetX11RootWindow(), False, + int result = XSendEvent(gfx::GetXDisplay(), GetX11RootWindow(), False, SubstructureNotifyMask, &event); return result == Success; } @@ -1453,7 +1504,7 @@ bool IsX11WindowFullScreen(XID window) { // // TODO(erg): Actually doing this correctly would require pulling out xrandr, // which we don't even do in the desktop screen yet. - ::Display* display = ui::GetXDisplay(); + ::XDisplay* display = gfx::GetXDisplay(); ::Screen* screen = DefaultScreenOfDisplay(display); int width = WidthOfScreen(screen); int height = HeightOfScreen(screen); @@ -1481,7 +1532,7 @@ void InitXKeyEventForTesting(EventType type, int flags, XEvent* event) { CHECK(event); - Display* display = GetXDisplay(); + XDisplay* display = gfx::GetXDisplay(); XKeyEvent key_event; key_event.type = XKeyEventType(type); CHECK_NE(0, key_event.type); @@ -1531,7 +1582,7 @@ void XScopedImage::reset(XImage* image) { image_ = image; } -XScopedCursor::XScopedCursor(::Cursor cursor, Display* display) +XScopedCursor::XScopedCursor(::Cursor cursor, XDisplay* display) : cursor_(cursor), display_(display) { } @@ -1553,7 +1604,7 @@ void XScopedCursor::reset(::Cursor cursor) { // ---------------------------------------------------------------------------- // These functions are declared in x11_util_internal.h because they require // XLib.h to be included, and it conflicts with many other headers. -XRenderPictFormat* GetRenderARGB32Format(Display* dpy) { +XRenderPictFormat* GetRenderARGB32Format(XDisplay* dpy) { static XRenderPictFormat* pictformat = NULL; if (pictformat) return pictformat; @@ -1589,7 +1640,7 @@ XRenderPictFormat* GetRenderARGB32Format(Display* dpy) { return pictformat; } -XRenderPictFormat* GetRenderVisualFormat(Display* dpy, Visual* visual) { +XRenderPictFormat* GetRenderVisualFormat(XDisplay* dpy, Visual* visual) { DCHECK(QueryRenderSupport(dpy)); CachedPictFormats* formats = get_cached_pict_formats(); @@ -1633,7 +1684,7 @@ void SetX11ErrorHandlers(XErrorHandler error_handler, io_error_handler ? io_error_handler : DefaultX11IOErrorHandler); } -void LogErrorEventDescription(Display* dpy, +void LogErrorEventDescription(XDisplay* dpy, const XErrorEvent& error_event) { char error_str[256]; char request_str[256]; @@ -1665,7 +1716,7 @@ void LogErrorEventDescription(Display* dpy, XFreeExtensionList(ext_list); } - LOG(ERROR) + LOG(WARNING) << "X error received: " << "serial " << error_event.serial << ", " << "error_code " << static_cast<int>(error_event.error_code) diff --git a/chromium/ui/base/x/x11_util.h b/chromium/ui/base/x/x11_util.h index c1c72ba0191..c528e908900 100644 --- a/chromium/ui/base/x/x11_util.h +++ b/chromium/ui/base/x/x11_util.h @@ -17,20 +17,17 @@ #include "base/basictypes.h" #include "base/event_types.h" #include "base/memory/ref_counted_memory.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/base/ui_export.h" +#include "ui/events/event_constants.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/point.h" +#include "ui/gfx/x/x11_types.h" typedef unsigned long Atom; -typedef unsigned long XID; typedef unsigned long XSharedMemoryId; // ShmSeg in the X headers. -typedef struct _XDisplay Display; typedef unsigned long Cursor; typedef struct _XcursorImage XcursorImage; typedef union _XEvent XEvent; -typedef struct _XImage XImage; -typedef struct _XGC *GC; #if defined(TOOLKIT_GTK) typedef struct _GdkDrawable GdkWindow; @@ -39,13 +36,15 @@ typedef struct _GtkWindow GtkWindow; #endif namespace gfx { +class Canvas; +class Point; class Rect; } class SkBitmap; namespace ui { -// These functions use the GDK default display and this /must/ be called from +// These functions use the default display and this /must/ be called from // the UI thread. Thus, they don't support multiple displays. // These functions cache their results --------------------------------- @@ -54,11 +53,6 @@ namespace ui { UI_EXPORT bool XDisplayExists(); // Return an X11 connection for the current, primary display. -// TODO(oshima|evan): This assume there is one display and dosn't work -// undef mutiple displays/monitor environment. Remove this and change the -// chrome codebase to get the display from window. -UI_EXPORT Display* GetXDisplay(); - // X shared memory comes in three flavors: // 1) No SHM support, // 2) SHM putimage, @@ -69,13 +63,13 @@ enum SharedMemorySupport { SHARED_MEMORY_PIXMAP }; // Return the shared memory type of our X connection. -UI_EXPORT SharedMemorySupport QuerySharedMemorySupport(Display* dpy); +UI_EXPORT SharedMemorySupport QuerySharedMemorySupport(XDisplay* dpy); // Return true iff the display supports Xrender -UI_EXPORT bool QueryRenderSupport(Display* dpy); +UI_EXPORT bool QueryRenderSupport(XDisplay* dpy); // Return the default screen number for the display -int GetDefaultScreen(Display* display); +int GetDefaultScreen(XDisplay* display); // Returns an X11 Cursor, sharable across the process. // |cursor_shape| is an X font cursor shape, see XCreateFontCursor(). @@ -151,7 +145,7 @@ UI_EXPORT void SetHideTitlebarWhenMaximizedProperty( UI_EXPORT void ClearX11DefaultRootWindow(); // Return the number of bits-per-pixel for a pixmap of the given depth -UI_EXPORT int BitsPerPixelForPixmapDepth(Display* display, int depth); +UI_EXPORT int BitsPerPixelForPixmapDepth(XDisplay* display, int depth); // Returns true if |window| is visible. UI_EXPORT bool IsWindowVisible(XID window); @@ -209,6 +203,12 @@ UI_EXPORT bool SetAtomArrayProperty(XID window, // Gets the X atom for default display corresponding to atom_name. Atom GetAtom(const char* atom_name); +// Sets the WM_CLASS attribute for a given X11 window. +UI_EXPORT void SetWindowClassHint(XDisplay* display, + XID window, + std::string res_name, + std::string res_class); + // Get |window|'s parent window, or None if |window| is the root window. UI_EXPORT XID GetParentWindow(XID window); @@ -221,7 +221,7 @@ static const int kAllDesktops = -1; bool GetWindowDesktop(XID window, int* desktop); // Translates an X11 error code into a printable string. -UI_EXPORT std::string GetX11ErrorString(Display* display, int err); +UI_EXPORT std::string GetX11ErrorString(XDisplay* display, int err); // Implementers of this interface receive a notification for every X window of // the main display. @@ -255,19 +255,29 @@ void RestackWindow(XID window, XID sibling, bool above); // Return a handle to a X ShmSeg. |shared_memory_key| is a SysV // IPC key. The shared memory region must contain 32-bit pixels. -UI_EXPORT XSharedMemoryId AttachSharedMemory(Display* display, +UI_EXPORT XSharedMemoryId AttachSharedMemory(XDisplay* display, int shared_memory_support); -UI_EXPORT void DetachSharedMemory(Display* display, XSharedMemoryId shmseg); +UI_EXPORT void DetachSharedMemory(XDisplay* display, XSharedMemoryId shmseg); + +// Copies |source_bounds| from |drawable| to |canvas| at offset |dest_offset|. +// |source_bounds| is in physical pixels, while |dest_offset| is relative to +// the canvas's scale. Note that this function is slow since it uses +// XGetImage() to copy the data from the X server to this process before +// copying it to |canvas|. +UI_EXPORT bool CopyAreaToCanvas(XID drawable, + gfx::Rect source_bounds, + gfx::Point dest_offset, + gfx::Canvas* canvas); // Return a handle to an XRender picture where |pixmap| is a handle to a // pixmap containing Skia ARGB data. -UI_EXPORT XID CreatePictureFromSkiaPixmap(Display* display, XID pixmap); +UI_EXPORT XID CreatePictureFromSkiaPixmap(XDisplay* display, XID pixmap); // Draws ARGB data on the given pixmap using the given GC, converting to the // server side visual depth as needed. Destination is assumed to be the same // dimensions as |data| or larger. |data| is also assumed to be in row order // with each line being exactly |width| * 4 bytes long. -UI_EXPORT void PutARGBImage(Display* display, +UI_EXPORT void PutARGBImage(XDisplay* display, void* visual, int depth, XID pixmap, void* pixmap_gc, const uint8* data, @@ -277,7 +287,7 @@ UI_EXPORT void PutARGBImage(Display* display, // - |data_width| and |data_height| refer to the data image // - |src_x|, |src_y|, |copy_width| and |copy_height| define source region // - |dst_x|, |dst_y|, |copy_width| and |copy_height| define destination region -UI_EXPORT void PutARGBImage(Display* display, +UI_EXPORT void PutARGBImage(XDisplay* display, void* visual, int depth, XID pixmap, void* pixmap_gc, const uint8* data, @@ -286,8 +296,8 @@ UI_EXPORT void PutARGBImage(Display* display, int dst_x, int dst_y, int copy_width, int copy_height); -void FreePicture(Display* display, XID picture); -void FreePixmap(Display* display, XID pixmap); +void FreePicture(XDisplay* display, XID picture); +void FreePixmap(XDisplay* display, XID pixmap); enum WindowManagerName { WM_UNKNOWN, @@ -401,7 +411,7 @@ class UI_EXPORT XScopedImage { class UI_EXPORT XScopedCursor { public: // Keeps track of |cursor| created with |display|. - XScopedCursor(::Cursor cursor, Display* display); + XScopedCursor(::Cursor cursor, XDisplay* display); ~XScopedCursor(); ::Cursor get() const; @@ -409,7 +419,7 @@ class UI_EXPORT XScopedCursor { private: ::Cursor cursor_; - Display* display_; + XDisplay* display_; DISALLOW_COPY_AND_ASSIGN(XScopedCursor); }; diff --git a/chromium/ui/compositor/DEPS b/chromium/ui/compositor/DEPS index 66c3932cf54..7a2d98ba46f 100644 --- a/chromium/ui/compositor/DEPS +++ b/chromium/ui/compositor/DEPS @@ -4,6 +4,5 @@ include_rules = [ "+cc", "+third_party/WebKit/public/platform/WebGraphicsContext3D.h", - "+third_party/WebKit/public/platform/WebString.h", "+webkit/common/gpu", ] diff --git a/chromium/ui/compositor/OWNERS b/chromium/ui/compositor/OWNERS index 1faff3677f2..d2216223c29 100644 --- a/chromium/ui/compositor/OWNERS +++ b/chromium/ui/compositor/OWNERS @@ -1,3 +1,6 @@ danakj@chromium.org piman@chromium.org vollick@chromium.org + +# Animation +per-file *animat*=ajuma@chromium.org diff --git a/chromium/ui/compositor/compositor.cc b/chromium/ui/compositor/compositor.cc index f16e56bf827..47ded5eb690 100644 --- a/chromium/ui/compositor/compositor.cc +++ b/chromium/ui/compositor/compositor.cc @@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/command_line.h" +#include "base/debug/trace_event.h" #include "base/memory/singleton.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" @@ -16,6 +17,8 @@ #include "base/threading/thread.h" #include "base/threading/thread_restrictions.h" #include "cc/base/switches.h" +#include "cc/debug/test_context_provider.h" +#include "cc/debug/test_web_graphics_context_3d.h" #include "cc/input/input_handler.h" #include "cc/layers/layer.h" #include "cc/output/context_provider.h" @@ -24,15 +27,14 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "ui/compositor/compositor_observer.h" #include "ui/compositor/compositor_switches.h" -#include "ui/compositor/context_provider_from_context_factory.h" #include "ui/compositor/dip_util.h" #include "ui/compositor/layer.h" #include "ui/compositor/reflector.h" -#include "ui/compositor/test_web_graphics_context_3d.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_surface.h" #include "ui/gl/gl_switches.h" +#include "webkit/common/gpu/context_provider_in_process.h" #include "webkit/common/gpu/grcontext_for_webgraphicscontext3d.h" #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h" @@ -108,13 +110,24 @@ bool DefaultContextFactory::Initialize() { scoped_ptr<cc::OutputSurface> DefaultContextFactory::CreateOutputSurface( Compositor* compositor) { - return make_scoped_ptr(new cc::OutputSurface( - CreateContextCommon(compositor, false))); -} + WebKit::WebGraphicsContext3D::Attributes attrs; + attrs.depth = false; + attrs.stencil = false; + attrs.antialias = false; + attrs.shareResources = true; -scoped_ptr<WebKit::WebGraphicsContext3D> -DefaultContextFactory::CreateOffscreenContext() { - return CreateContextCommon(NULL, true); + using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl; + scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context3d( + WebGraphicsContext3DInProcessCommandBufferImpl::CreateViewContext( + attrs, compositor->widget())); + CHECK(context3d); + + using webkit::gpu::ContextProviderInProcess; + scoped_refptr<ContextProviderInProcess> context_provider = + ContextProviderInProcess::Create(context3d.Pass(), + "UICompositor"); + + return make_scoped_ptr(new cc::OutputSurface(context_provider)); } scoped_refptr<Reflector> DefaultContextFactory::CreateReflector( @@ -132,7 +145,7 @@ DefaultContextFactory::OffscreenContextProviderForMainThread() { if (!offscreen_contexts_main_thread_.get() || !offscreen_contexts_main_thread_->DestroyedOnMainThread()) { offscreen_contexts_main_thread_ = - ContextProviderFromContextFactory::CreateForOffscreen(this); + webkit::gpu::ContextProviderInProcess::CreateOffscreen(); if (offscreen_contexts_main_thread_.get() && !offscreen_contexts_main_thread_->BindToCurrentThread()) offscreen_contexts_main_thread_ = NULL; @@ -145,7 +158,7 @@ DefaultContextFactory::OffscreenContextProviderForCompositorThread() { if (!offscreen_contexts_compositor_thread_.get() || !offscreen_contexts_compositor_thread_->DestroyedOnMainThread()) { offscreen_contexts_compositor_thread_ = - ContextProviderFromContextFactory::CreateForOffscreen(this); + webkit::gpu::ContextProviderInProcess::CreateOffscreen(); } return offscreen_contexts_compositor_thread_; } @@ -155,39 +168,14 @@ void DefaultContextFactory::RemoveCompositor(Compositor* compositor) { bool DefaultContextFactory::DoesCreateTestContexts() { return false; } -scoped_ptr<WebKit::WebGraphicsContext3D> -DefaultContextFactory::CreateContextCommon(Compositor* compositor, - bool offscreen) { - DCHECK(offscreen || compositor); - WebKit::WebGraphicsContext3D::Attributes attrs; - attrs.depth = false; - attrs.stencil = false; - attrs.antialias = false; - attrs.shareResources = true; - using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl; - if (offscreen) { - return WebGraphicsContext3DInProcessCommandBufferImpl:: - CreateOffscreenContext(attrs); - } - return WebGraphicsContext3DInProcessCommandBufferImpl::CreateViewContext( - attrs, compositor->widget()); -} - TestContextFactory::TestContextFactory() {} TestContextFactory::~TestContextFactory() {} scoped_ptr<cc::OutputSurface> TestContextFactory::CreateOutputSurface( Compositor* compositor) { - return make_scoped_ptr(new cc::OutputSurface(CreateOffscreenContext())); -} - -scoped_ptr<WebKit::WebGraphicsContext3D> -TestContextFactory::CreateOffscreenContext() { - scoped_ptr<ui::TestWebGraphicsContext3D> context( - new ui::TestWebGraphicsContext3D); - context->Initialize(); - return context.PassAs<WebKit::WebGraphicsContext3D>(); + return make_scoped_ptr( + new cc::OutputSurface(cc::TestContextProvider::Create())); } scoped_refptr<Reflector> TestContextFactory::CreateReflector( @@ -203,8 +191,7 @@ scoped_refptr<cc::ContextProvider> TestContextFactory::OffscreenContextProviderForMainThread() { if (!offscreen_contexts_main_thread_.get() || offscreen_contexts_main_thread_->DestroyedOnMainThread()) { - offscreen_contexts_main_thread_ = - ContextProviderFromContextFactory::CreateForOffscreen(this); + offscreen_contexts_main_thread_ = cc::TestContextProvider::Create(); CHECK(offscreen_contexts_main_thread_->BindToCurrentThread()); } return offscreen_contexts_main_thread_; @@ -214,8 +201,7 @@ scoped_refptr<cc::ContextProvider> TestContextFactory::OffscreenContextProviderForCompositorThread() { if (!offscreen_contexts_compositor_thread_.get() || offscreen_contexts_compositor_thread_->DestroyedOnMainThread()) { - offscreen_contexts_compositor_thread_ = - ContextProviderFromContextFactory::CreateForOffscreen(this); + offscreen_contexts_compositor_thread_ = cc::TestContextProvider::Create(); } return offscreen_contexts_compositor_thread_; } @@ -400,6 +386,8 @@ Compositor::Compositor(CompositorDelegate* delegate, ContextFactory::GetInstance()->DoesCreateTestContexts() ? kTestRefreshRate : kDefaultRefreshRate; + settings.deadline_scheduling_enabled = + switches::IsUIDeadlineSchedulingEnabled(); settings.partial_swap_enabled = !command_line->HasSwitch(cc::switches::kUIDisablePartialSwap); settings.per_tile_painting_enabled = @@ -434,6 +422,8 @@ Compositor::Compositor(CompositorDelegate* delegate, } Compositor::~Compositor() { + TRACE_EVENT0("shutdown", "Compositor::destructor"); + DCHECK(g_compositor_initialized); CancelCompositorLock(); @@ -453,7 +443,10 @@ Compositor::~Compositor() { // static void Compositor::InitializeContextFactoryForTests(bool allow_test_contexts) { - DCHECK(!g_context_factory) << "ContextFactory already initialized."; + // The factory may already have been initialized by the content layer, in + // which case, use that one. + if (g_context_factory) + return; DCHECK(!g_implicit_factory) << "ContextFactory for tests already initialized."; diff --git a/chromium/ui/compositor/compositor.gyp b/chromium/ui/compositor/compositor.gyp index 57a4aafae21..de62e6d8af9 100644 --- a/chromium/ui/compositor/compositor.gyp +++ b/chromium/ui/compositor/compositor.gyp @@ -30,8 +30,6 @@ 'compositor_observer.h', 'compositor_switches.cc', 'compositor_switches.h', - 'context_provider_from_context_factory.cc', - 'context_provider_from_context_factory.h', 'debug_utils.cc', 'debug_utils.h', 'dip_util.cc', @@ -58,9 +56,6 @@ 'scoped_animation_duration_scale_mode.h', 'scoped_layer_animation_settings.cc', 'scoped_layer_animation_settings.h', - # UI tests need TestWebGraphicsContext3D, so we always build it. - 'test_web_graphics_context_3d.cc', - 'test_web_graphics_context_3d.h', 'transform_animation_curve_adapter.cc', 'transform_animation_curve_adapter.h', ], @@ -128,6 +123,7 @@ 'test/test_layer_animation_observer.h', 'test/test_utils.cc', 'test/test_utils.h', + 'transform_animation_curve_adapter_unittest.cc', ], 'conditions': [ # osmesa GL implementation is used on linux. diff --git a/chromium/ui/compositor/compositor.h b/chromium/ui/compositor/compositor.h index 92cdd7194f8..e6ce889f525 100644 --- a/chromium/ui/compositor/compositor.h +++ b/chromium/ui/compositor/compositor.h @@ -34,6 +34,7 @@ class ContextProvider; class Layer; class LayerTreeDebugState; class LayerTreeHost; +class TestContextProvider; } namespace gfx { @@ -49,6 +50,13 @@ namespace WebKit { class WebGraphicsContext3D; } +namespace webkit { +namespace gpu { +class ContextProviderInProcess; +class WebGraphicsContext3DInProcessCommandBufferImpl; +} +} + namespace ui { class Compositor; @@ -80,10 +88,6 @@ class COMPOSITOR_EXPORT ContextFactory { virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface( Compositor* compositor) = 0; - // Creates a context used for offscreen rendering. This context can be shared - // with all compositors. - virtual scoped_ptr<WebKit::WebGraphicsContext3D> CreateOffscreenContext() = 0; - // Creates a reflector that copies the content of the |mirrored_compositor| // onto |mirroing_layer|. virtual scoped_refptr<Reflector> CreateReflector( @@ -114,8 +118,6 @@ class COMPOSITOR_EXPORT DefaultContextFactory : public ContextFactory { // ContextFactory implementation virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface( Compositor* compositor) OVERRIDE; - virtual scoped_ptr<WebKit::WebGraphicsContext3D> CreateOffscreenContext() - OVERRIDE; virtual scoped_refptr<Reflector> CreateReflector( Compositor* compositor, @@ -132,13 +134,9 @@ class COMPOSITOR_EXPORT DefaultContextFactory : public ContextFactory { bool Initialize(); private: - scoped_ptr<WebKit::WebGraphicsContext3D> CreateContextCommon( - Compositor* compositor, - bool offscreen); - - scoped_refptr<ContextProviderFromContextFactory> + scoped_refptr<webkit::gpu::ContextProviderInProcess> offscreen_contexts_main_thread_; - scoped_refptr<ContextProviderFromContextFactory> + scoped_refptr<webkit::gpu::ContextProviderInProcess> offscreen_contexts_compositor_thread_; DISALLOW_COPY_AND_ASSIGN(DefaultContextFactory); @@ -153,8 +151,6 @@ class COMPOSITOR_EXPORT TestContextFactory : public ContextFactory { // ContextFactory implementation virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface( Compositor* compositor) OVERRIDE; - virtual scoped_ptr<WebKit::WebGraphicsContext3D> CreateOffscreenContext() - OVERRIDE; virtual scoped_refptr<Reflector> CreateReflector( Compositor* mirrored_compositor, @@ -169,10 +165,8 @@ class COMPOSITOR_EXPORT TestContextFactory : public ContextFactory { virtual bool DoesCreateTestContexts() OVERRIDE; private: - scoped_refptr<ContextProviderFromContextFactory> - offscreen_contexts_main_thread_; - scoped_refptr<ContextProviderFromContextFactory> - offscreen_contexts_compositor_thread_; + scoped_refptr<cc::TestContextProvider> offscreen_contexts_main_thread_; + scoped_refptr<cc::TestContextProvider> offscreen_contexts_compositor_thread_; DISALLOW_COPY_AND_ASSIGN(TestContextFactory); }; diff --git a/chromium/ui/compositor/compositor_switches.cc b/chromium/ui/compositor/compositor_switches.cc index 7f1bd230a25..39b929a954d 100644 --- a/chromium/ui/compositor/compositor_switches.cc +++ b/chromium/ui/compositor/compositor_switches.cc @@ -4,12 +4,18 @@ #include "ui/compositor/compositor_switches.h" +#include "base/command_line.h" + namespace switches { const char kDisableTestCompositor[] = "disable-test-compositor"; +const char kUIDisableDeadlineScheduling[] = "ui-disable-deadline-scheduling"; + const char kUIDisableThreadedCompositing[] = "ui-disable-threaded-compositing"; +const char kUIEnableDeadlineScheduling[] = "ui-enable-deadline-scheduling"; + const char kUIEnableSoftwareCompositing[] = "ui-enable-software-compositing"; const char kUIEnableThreadedCompositing[] = "ui-enable-threaded-compositing"; @@ -18,4 +24,17 @@ const char kUIMaxFramesPending[] = "ui-max-frames-pending"; const char kUIShowPaintRects[] = "ui-show-paint-rects"; +bool IsUIDeadlineSchedulingEnabled() { + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + + // Default to disabled. + bool enabled = false; + + // Flags override. + enabled |= command_line.HasSwitch(switches::kUIEnableDeadlineScheduling); + enabled &= !command_line.HasSwitch(switches::kUIDisableDeadlineScheduling); + + return enabled; +} + } // namespace switches diff --git a/chromium/ui/compositor/compositor_switches.h b/chromium/ui/compositor/compositor_switches.h index 5b59477a948..2bf2b242260 100644 --- a/chromium/ui/compositor/compositor_switches.h +++ b/chromium/ui/compositor/compositor_switches.h @@ -10,12 +10,16 @@ namespace switches { COMPOSITOR_EXPORT extern const char kDisableTestCompositor[]; +COMPOSITOR_EXPORT extern const char kUIDisableDeadlineScheduling[]; COMPOSITOR_EXPORT extern const char kUIDisableThreadedCompositing[]; +COMPOSITOR_EXPORT extern const char kUIEnableDeadlineScheduling[]; COMPOSITOR_EXPORT extern const char kUIEnableSoftwareCompositing[]; COMPOSITOR_EXPORT extern const char kUIEnableThreadedCompositing[]; COMPOSITOR_EXPORT extern const char kUIMaxFramesPending[]; COMPOSITOR_EXPORT extern const char kUIShowPaintRects[]; +COMPOSITOR_EXPORT bool IsUIDeadlineSchedulingEnabled(); + } // namespace switches #endif // UI_COMPOSITOR_COMPOSITOR_SWITCHES_H_ diff --git a/chromium/ui/compositor/context_provider_from_context_factory.cc b/chromium/ui/compositor/context_provider_from_context_factory.cc deleted file mode 100644 index 262998a886a..00000000000 --- a/chromium/ui/compositor/context_provider_from_context_factory.cc +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 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 "context_provider_from_context_factory.h" - -#include "base/logging.h" - -namespace ui { - -// static -scoped_refptr<ContextProviderFromContextFactory> -ContextProviderFromContextFactory::CreateForOffscreen(ContextFactory* factory) { - scoped_refptr<ContextProviderFromContextFactory> provider = - new ContextProviderFromContextFactory(factory); - if (!provider->InitializeOnMainThread()) - return NULL; - return provider; -} - -ContextProviderFromContextFactory::ContextProviderFromContextFactory( - ContextFactory* factory) - : factory_(factory), - destroyed_(false) { -} - -ContextProviderFromContextFactory::~ContextProviderFromContextFactory() { -} - -bool ContextProviderFromContextFactory::BindToCurrentThread() { - DCHECK(context3d_); - return context3d_->makeContextCurrent(); -} - -WebKit::WebGraphicsContext3D* ContextProviderFromContextFactory::Context3d() { - DCHECK(context3d_); - return context3d_.get(); -} - -class GrContext* ContextProviderFromContextFactory::GrContext() { - DCHECK(context3d_); - - if (!gr_context_) { - gr_context_.reset( - new webkit::gpu::GrContextForWebGraphicsContext3D(context3d_.get())); - } - return gr_context_->get(); -} - -void ContextProviderFromContextFactory::VerifyContexts() { - DCHECK(context3d_); - - if (context3d_->isContextLost()) { - base::AutoLock lock(destroyed_lock_); - destroyed_ = true; - } -} - -bool ContextProviderFromContextFactory::DestroyedOnMainThread() { - base::AutoLock lock(destroyed_lock_); - return destroyed_; -} - -void ContextProviderFromContextFactory::SetLostContextCallback( - const LostContextCallback& cb) { - NOTIMPLEMENTED(); -} - -bool ContextProviderFromContextFactory::InitializeOnMainThread() { - if (context3d_) - return true; - context3d_ = factory_->CreateOffscreenContext(); - return !!context3d_; -} - -} // namespace ui diff --git a/chromium/ui/compositor/context_provider_from_context_factory.h b/chromium/ui/compositor/context_provider_from_context_factory.h deleted file mode 100644 index 57be7f47efd..00000000000 --- a/chromium/ui/compositor/context_provider_from_context_factory.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 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. - -#ifndef UI_COMPOSITOR_CONTEXT_PROVIDER_FROM_CONTEXT_FACTORY_H_ -#define UI_COMPOSITOR_CONTEXT_PROVIDER_FROM_CONTEXT_FACTORY_H_ - -#include "base/synchronization/lock.h" -#include "cc/output/context_provider.h" -#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" -#include "ui/compositor/compositor.h" -#include "webkit/common/gpu/grcontext_for_webgraphicscontext3d.h" - -namespace ui { - -class ContextProviderFromContextFactory - : public cc::ContextProvider { - public: - static scoped_refptr<ContextProviderFromContextFactory> CreateForOffscreen( - ContextFactory* factory); - - virtual bool BindToCurrentThread() OVERRIDE; - virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE; - virtual class GrContext* GrContext() OVERRIDE; - virtual void VerifyContexts() OVERRIDE; - virtual bool DestroyedOnMainThread() OVERRIDE; - virtual void SetLostContextCallback(const LostContextCallback& cb) OVERRIDE; - - protected: - ContextProviderFromContextFactory(ContextFactory* factory); - virtual ~ContextProviderFromContextFactory(); - - bool InitializeOnMainThread(); - - private: - ContextFactory* factory_; - base::Lock destroyed_lock_; - bool destroyed_; - scoped_ptr<WebKit::WebGraphicsContext3D> context3d_; - scoped_ptr<webkit::gpu::GrContextForWebGraphicsContext3D> gr_context_; -}; - -} // namespace ui - -#endif // UI_COMPOSITOR_CONTEXT_PROVIDER_FROM_CONTEXT_FACTORY_H_ diff --git a/chromium/ui/compositor/debug_utils.cc b/chromium/ui/compositor/debug_utils.cc index 016ff17eeb1..e1f62f9d42d 100644 --- a/chromium/ui/compositor/debug_utils.cc +++ b/chromium/ui/compositor/debug_utils.cc @@ -28,9 +28,8 @@ void PrintLayerHierarchyImp(const Layer* layer, gfx::Point mouse_location, std::wostringstream* out) { std::string indent_str(indent, ' '); - std::string content_indent_str(indent+1, ' '); - layer->transform().TransformPointReverse(mouse_location); + layer->transform().TransformPointReverse(&mouse_location); bool mouse_inside_layer_bounds = layer->bounds().Contains(mouse_location); mouse_location.Offset(-layer->bounds().x(), -layer->bounds().y()); diff --git a/chromium/ui/compositor/dip_util.cc b/chromium/ui/compositor/dip_util.cc index 1f6309a42b5..2d95af63830 100644 --- a/chromium/ui/compositor/dip_util.cc +++ b/chromium/ui/compositor/dip_util.cc @@ -5,7 +5,6 @@ #include "ui/compositor/dip_util.h" #include "base/command_line.h" -#include "ui/base/ui_base_switches.h" #include "ui/compositor/compositor.h" #include "ui/compositor/compositor_switches.h" #include "ui/compositor/layer.h" diff --git a/chromium/ui/compositor/float_animation_curve_adapter.cc b/chromium/ui/compositor/float_animation_curve_adapter.cc index e97fbf0b700..ec41f964d91 100644 --- a/chromium/ui/compositor/float_animation_curve_adapter.cc +++ b/chromium/ui/compositor/float_animation_curve_adapter.cc @@ -7,7 +7,7 @@ namespace ui { FloatAnimationCurveAdapter::FloatAnimationCurveAdapter( - Tween::Type tween_type, + gfx::Tween::Type tween_type, float initial_value, float target_value, base::TimeDelta duration) @@ -36,9 +36,10 @@ float FloatAnimationCurveAdapter::GetValue(double t) const { if (t <= 0.0) return initial_value_; double progress = t / duration_.InSecondsF(); - return Tween::ValueBetween(Tween::CalculateValue(tween_type_, progress), - initial_value_, - target_value_); + return gfx::Tween::ValueBetween( + gfx::Tween::CalculateValue(tween_type_, progress), + initial_value_, + target_value_); } } // namespace ui diff --git a/chromium/ui/compositor/float_animation_curve_adapter.h b/chromium/ui/compositor/float_animation_curve_adapter.h index 0e073aaa73f..9959772769f 100644 --- a/chromium/ui/compositor/float_animation_curve_adapter.h +++ b/chromium/ui/compositor/float_animation_curve_adapter.h @@ -7,13 +7,13 @@ #include "base/time/time.h" #include "cc/animation/animation_curve.h" -#include "ui/base/animation/tween.h" +#include "ui/gfx/animation/tween.h" namespace ui { class FloatAnimationCurveAdapter : public cc::FloatAnimationCurve { public: - FloatAnimationCurveAdapter(Tween::Type tween_type, + FloatAnimationCurveAdapter(gfx::Tween::Type tween_type, float initial_value, float target_value, base::TimeDelta duration); @@ -26,7 +26,7 @@ class FloatAnimationCurveAdapter : public cc::FloatAnimationCurve { virtual float GetValue(double t) const OVERRIDE; private: - Tween::Type tween_type_; + gfx::Tween::Type tween_type_; float initial_value_; float target_value_; base::TimeDelta duration_; diff --git a/chromium/ui/compositor/layer.cc b/chromium/ui/compositor/layer.cc index 6c0fde3e1c5..1e7a029f569 100644 --- a/chromium/ui/compositor/layer.cc +++ b/chromium/ui/compositor/layer.cc @@ -20,10 +20,10 @@ #include "cc/output/filter_operation.h" #include "cc/output/filter_operations.h" #include "cc/resources/transferable_resource.h" -#include "ui/base/animation/animation.h" #include "ui/compositor/compositor_switches.h" #include "ui/compositor/dip_util.h" #include "ui/compositor/layer_animator.h" +#include "ui/gfx/animation/animation.h" #include "ui/gfx/canvas.h" #include "ui/gfx/display.h" #include "ui/gfx/interpolated_transform.h" @@ -444,6 +444,7 @@ void Layer::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) { DCHECK(parent_->cc_layer_); parent_->cc_layer_->ReplaceChild(cc_layer_, new_layer); } + cc_layer_->SetLayerClient(NULL); cc_layer_->RemoveLayerAnimationEventObserver(this); new_layer->SetOpacity(cc_layer_->opacity()); new_layer->SetTransform(cc_layer_->transform()); @@ -460,6 +461,7 @@ void Layer::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) { DCHECK(children_[i]->cc_layer_); cc_layer_->AddChild(children_[i]->cc_layer_); } + cc_layer_->SetLayerClient(this); cc_layer_->SetAnchorPoint(gfx::PointF()); cc_layer_->SetContentsOpaque(fills_bounds_opaquely_); cc_layer_->SetForceRenderSurface(force_render_surface_); @@ -496,13 +498,16 @@ void Layer::SetExternalTexture(Texture* texture) { cc::ContentLayer::Create(this); SwitchToLayer(new_layer); content_layer_ = new_layer; + mailbox_ = cc::TextureMailbox(); } } RecomputeDrawsContentAndUVRect(); } -void Layer::SetTextureMailbox(const cc::TextureMailbox& mailbox, - float scale_factor) { +void Layer::SetTextureMailbox( + const cc::TextureMailbox& mailbox, + scoped_ptr<cc::SingleReleaseCallback> release_callback, + float scale_factor) { DCHECK_EQ(type_, LAYER_TEXTURED); DCHECK(!solid_color_layer_.get()); layer_updated_externally_ = true; @@ -514,7 +519,7 @@ void Layer::SetTextureMailbox(const cc::TextureMailbox& mailbox, SwitchToLayer(new_layer); texture_layer_ = new_layer; } - texture_layer_->SetTextureMailbox(mailbox); + texture_layer_->SetTextureMailbox(mailbox, release_callback.Pass()); mailbox_ = mailbox; mailbox_scale_factor_ = scale_factor; RecomputeDrawsContentAndUVRect(); @@ -523,8 +528,7 @@ void Layer::SetTextureMailbox(const cc::TextureMailbox& mailbox, cc::TextureMailbox Layer::GetTextureMailbox(float* scale_factor) { if (scale_factor) *scale_factor = mailbox_scale_factor_; - cc::TextureMailbox::ReleaseCallback callback; - return mailbox_.CopyWithNewCallback(callback); + return mailbox_; } void Layer::SetDelegatedFrame(scoped_ptr<cc::DelegatedFrameData> frame, @@ -552,7 +556,7 @@ void Layer::SetDelegatedFrame(scoped_ptr<cc::DelegatedFrameData> frame, } void Layer::TakeUnusedResourcesForChildCompositor( - cc::TransferableResourceArray* list) { + cc::ReturnedResourceArray* list) { if (delegated_renderer_layer_.get()) delegated_renderer_layer_->TakeUnusedResourcesForChildCompositor(list); } @@ -662,8 +666,10 @@ WebKit::WebGraphicsContext3D* Layer::Context3d() { return NULL; } -bool Layer::PrepareTextureMailbox(cc::TextureMailbox* mailbox, - bool use_shared_memory) { +bool Layer::PrepareTextureMailbox( + cc::TextureMailbox* mailbox, + scoped_ptr<cc::SingleReleaseCallback>* release_callback, + bool use_shared_memory) { return false; } @@ -675,6 +681,10 @@ void Layer::SetForceRenderSurface(bool force) { cc_layer_->SetForceRenderSurface(force_render_surface_); } +std::string Layer::DebugName() { + return name_; +} + void Layer::OnAnimationStarted(const cc::AnimationEvent& event) { if (animator_.get()) animator_->OnThreadedAnimationStarted(event); @@ -708,7 +718,7 @@ bool Layer::ConvertPointForAncestor(const Layer* ancestor, gfx::Transform transform; bool result = GetTargetTransformRelativeTo(ancestor, &transform); gfx::Point3F p(*point); - transform.TransformPoint(p); + transform.TransformPoint(&p); *point = gfx::ToFlooredPoint(p.AsPointF()); return result; } @@ -718,7 +728,7 @@ bool Layer::ConvertPointFromAncestor(const Layer* ancestor, gfx::Transform transform; bool result = GetTargetTransformRelativeTo(ancestor, &transform); gfx::Point3F p(*point); - transform.TransformPointReverse(p); + transform.TransformPointReverse(&p); *point = gfx::ToFlooredPoint(p.AsPointF()); return result; } @@ -917,6 +927,7 @@ void Layer::CreateWebLayer() { cc_layer_->SetContentsOpaque(true); cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN); cc_layer_->AddLayerAnimationEventObserver(this); + cc_layer_->SetLayerClient(this); RecomputePosition(); } diff --git a/chromium/ui/compositor/layer.h b/chromium/ui/compositor/layer.h index aa78d93b73e..5b7e2173700 100644 --- a/chromium/ui/compositor/layer.h +++ b/chromium/ui/compositor/layer.h @@ -16,6 +16,7 @@ #include "cc/animation/layer_animation_event_observer.h" #include "cc/base/scoped_ptr_vector.h" #include "cc/layers/content_layer_client.h" +#include "cc/layers/layer_client.h" #include "cc/layers/texture_layer_client.h" #include "cc/resources/texture_mailbox.h" #include "third_party/skia/include/core/SkColor.h" @@ -38,8 +39,8 @@ class Layer; class ResourceUpdateQueue; class SolidColorLayer; class TextureLayer; -struct TransferableResource; -typedef std::vector<TransferableResource> TransferableResourceArray; +struct ReturnedResource; +typedef std::vector<ReturnedResource> ReturnedResourceArray; } namespace ui { @@ -62,6 +63,7 @@ class COMPOSITOR_EXPORT Layer : public LayerAnimationDelegate, NON_EXPORTED_BASE(public cc::ContentLayerClient), NON_EXPORTED_BASE(public cc::TextureLayerClient), + NON_EXPORTED_BASE(public cc::LayerClient), NON_EXPORTED_BASE(public cc::LayerAnimationEventObserver) { public: Layer(); @@ -254,7 +256,9 @@ class COMPOSITOR_EXPORT Layer // Set new TextureMailbox for this layer. Note that |mailbox| may hold a // shared memory resource or an actual mailbox for a texture. - void SetTextureMailbox(const cc::TextureMailbox& mailbox, float scale_factor); + void SetTextureMailbox(const cc::TextureMailbox& mailbox, + scoped_ptr<cc::SingleReleaseCallback> release_callback, + float scale_factor); cc::TextureMailbox GetTextureMailbox(float* scale_factor); // Sets a delegated frame, coming from a child compositor. @@ -267,7 +271,7 @@ class COMPOSITOR_EXPORT Layer // Gets unused resources to recycle to the child compositor. void TakeUnusedResourcesForChildCompositor( - cc::TransferableResourceArray* array); + cc::ReturnedResourceArray* array); // Sets the layer's fill color. May only be called for LAYER_SOLID_COLOR. void SetColor(SkColor color); @@ -320,8 +324,10 @@ class COMPOSITOR_EXPORT Layer // TextureLayerClient virtual unsigned PrepareTexture() OVERRIDE; virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE; - virtual bool PrepareTextureMailbox(cc::TextureMailbox* mailbox, - bool use_shared_memory) OVERRIDE; + virtual bool PrepareTextureMailbox( + cc::TextureMailbox* mailbox, + scoped_ptr<cc::SingleReleaseCallback>* release_callback, + bool use_shared_memory) OVERRIDE; float device_scale_factor() const { return device_scale_factor_; } @@ -330,6 +336,9 @@ class COMPOSITOR_EXPORT Layer void SetForceRenderSurface(bool force); bool force_render_surface() const { return force_render_surface_; } + // LayerClient + virtual std::string DebugName() OVERRIDE; + // LayerAnimationEventObserver virtual void OnAnimationStarted(const cc::AnimationEvent& event) OVERRIDE; @@ -471,7 +480,7 @@ class COMPOSITOR_EXPORT Layer cc::Layer* cc_layer_; // If true, the layer scales the canvas and the texture with the device scale - // factor as appropriate. When true, the texture size is in DIP. + // factor as apporpriate. When true, the texture size is in DIP. bool scale_content_; // A cached copy of |Compositor::device_scale_factor()|. diff --git a/chromium/ui/compositor/layer_animation_element.cc b/chromium/ui/compositor/layer_animation_element.cc index f70c1084a1d..1448660240f 100644 --- a/chromium/ui/compositor/layer_animation_element.cc +++ b/chromium/ui/compositor/layer_animation_element.cc @@ -7,13 +7,13 @@ #include "base/compiler_specific.h" #include "cc/animation/animation.h" #include "cc/animation/animation_id_provider.h" -#include "ui/base/animation/tween.h" #include "ui/compositor/float_animation_curve_adapter.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animation_delegate.h" #include "ui/compositor/layer_animator.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/compositor/transform_animation_curve_adapter.h" +#include "ui/gfx/animation/tween.h" #include "ui/gfx/interpolated_transform.h" namespace ui { @@ -63,7 +63,7 @@ class TransformTransition : public LayerAnimationElement { virtual bool OnProgress(double t, LayerAnimationDelegate* delegate) OVERRIDE { delegate->SetTransformFromAnimation( - Tween::ValueBetween(t, start_, target_)); + gfx::Tween::ValueBetween(t, start_, target_)); return true; } @@ -141,7 +141,8 @@ class BoundsTransition : public LayerAnimationElement { } virtual bool OnProgress(double t, LayerAnimationDelegate* delegate) OVERRIDE { - delegate->SetBoundsFromAnimation(Tween::ValueBetween(t, start_, target_)); + delegate->SetBoundsFromAnimation( + gfx::Tween::ValueBetween(t, start_, target_)); return true; } @@ -181,7 +182,8 @@ class OpacityTransition : public LayerAnimationElement { } virtual bool OnProgress(double t, LayerAnimationDelegate* delegate) OVERRIDE { - delegate->SetOpacityFromAnimation(Tween::ValueBetween(t, start_, target_)); + delegate->SetOpacityFromAnimation( + gfx::Tween::ValueBetween(t, start_, target_)); return true; } @@ -262,7 +264,7 @@ class BrightnessTransition : public LayerAnimationElement { virtual bool OnProgress(double t, LayerAnimationDelegate* delegate) OVERRIDE { delegate->SetBrightnessFromAnimation( - Tween::ValueBetween(t, start_, target_)); + gfx::Tween::ValueBetween(t, start_, target_)); return true; } @@ -303,7 +305,7 @@ class GrayscaleTransition : public LayerAnimationElement { virtual bool OnProgress(double t, LayerAnimationDelegate* delegate) OVERRIDE { delegate->SetGrayscaleFromAnimation( - Tween::ValueBetween(t, start_, target_)); + gfx::Tween::ValueBetween(t, start_, target_)); return true; } @@ -345,18 +347,18 @@ class ColorTransition : public LayerAnimationElement { virtual bool OnProgress(double t, LayerAnimationDelegate* delegate) OVERRIDE { delegate->SetColorFromAnimation( SkColorSetARGB( - Tween::ValueBetween(t, - static_cast<int>(SkColorGetA(start_)), - static_cast<int>(SkColorGetA(target_))), - Tween::ValueBetween(t, - static_cast<int>(SkColorGetR(start_)), - static_cast<int>(SkColorGetR(target_))), - Tween::ValueBetween(t, - static_cast<int>(SkColorGetG(start_)), - static_cast<int>(SkColorGetG(target_))), - Tween::ValueBetween(t, - static_cast<int>(SkColorGetB(start_)), - static_cast<int>(SkColorGetB(target_))))); + gfx::Tween::ValueBetween(t, + static_cast<int>(SkColorGetA(start_)), + static_cast<int>(SkColorGetA(target_))), + gfx::Tween::ValueBetween(t, + static_cast<int>(SkColorGetR(start_)), + static_cast<int>(SkColorGetR(target_))), + gfx::Tween::ValueBetween(t, + static_cast<int>(SkColorGetG(start_)), + static_cast<int>(SkColorGetG(target_))), + gfx::Tween::ValueBetween(t, + static_cast<int>(SkColorGetB(start_)), + static_cast<int>(SkColorGetB(target_))))); return true; } @@ -394,6 +396,10 @@ class ThreadedLayerAnimationElement : public LayerAnimationElement { } protected: + explicit ThreadedLayerAnimationElement(const LayerAnimationElement& element) + : LayerAnimationElement(element) { + } + virtual bool OnProgress(double t, LayerAnimationDelegate* delegate) OVERRIDE { if (t < 1.0) @@ -453,10 +459,10 @@ class ThreadedOpacityTransition : public ThreadedLayerAnimationElement { virtual void OnAbort(LayerAnimationDelegate* delegate) OVERRIDE { if (delegate && Started()) { ThreadedLayerAnimationElement::OnAbort(delegate); - delegate->SetOpacityFromAnimation(Tween::ValueBetween( - Tween::CalculateValue(tween_type(), last_progressed_fraction()), - start_, - target_)); + delegate->SetOpacityFromAnimation(gfx::Tween::ValueBetween( + gfx::Tween::CalculateValue(tween_type(), last_progressed_fraction()), + start_, + target_)); } } @@ -519,8 +525,8 @@ class ThreadedTransformTransition : public ThreadedLayerAnimationElement { virtual void OnAbort(LayerAnimationDelegate* delegate) OVERRIDE { if (delegate && Started()) { ThreadedLayerAnimationElement::OnAbort(delegate); - delegate->SetTransformFromAnimation(Tween::ValueBetween( - Tween::CalculateValue(tween_type(), last_progressed_fraction()), + delegate->SetTransformFromAnimation(gfx::Tween::ValueBetween( + gfx::Tween::CalculateValue(tween_type(), last_progressed_fraction()), start_, target_)); } @@ -563,6 +569,127 @@ class ThreadedTransformTransition : public ThreadedLayerAnimationElement { DISALLOW_COPY_AND_ASSIGN(ThreadedTransformTransition); }; +// InverseTransformTransision -------------------------------------------------- + +class InverseTransformTransition : public ThreadedLayerAnimationElement { + public: + InverseTransformTransition(const gfx::Transform& base_transform, + const LayerAnimationElement* uninverted_transition) + : ThreadedLayerAnimationElement(*uninverted_transition), + base_transform_(base_transform), + uninverted_transition_( + CheckAndCast<const ThreadedTransformTransition*>( + uninverted_transition)) { + } + virtual ~InverseTransformTransition() {} + + static InverseTransformTransition* Clone(const LayerAnimationElement* other) { + const InverseTransformTransition* other_inverse = + CheckAndCast<const InverseTransformTransition*>(other); + return new InverseTransformTransition( + other_inverse->base_transform_, other_inverse->uninverted_transition_); + } + + protected: + virtual void OnStart(LayerAnimationDelegate* delegate) OVERRIDE { + gfx::Transform start(delegate->GetTransformForAnimation()); + effective_start_ = base_transform_ * start; + + TargetValue target; + uninverted_transition_->GetTargetValue(&target); + base_target_ = target.transform; + + set_tween_type(uninverted_transition_->tween_type()); + + float device_scale_factor = delegate->GetDeviceScaleFactor(); + const gfx::Transform cc_base_start = Layer::ConvertTransformToCCTransform( + base_transform_, + device_scale_factor); + const gfx::Transform cc_base_target = Layer::ConvertTransformToCCTransform( + base_target_, + device_scale_factor); + TransformAnimationCurveAdapter base_curve(tween_type(), + cc_base_start, + cc_base_target, + duration()); + + const gfx::Transform cc_start = Layer::ConvertTransformToCCTransform( + start, device_scale_factor); + animation_curve_.reset(new InverseTransformCurveAdapter( + base_curve, cc_start, duration())); + computed_target_transform_ = ComputeWithBaseTransform(effective_start_, + base_target_); + } + + virtual void OnAbort(LayerAnimationDelegate* delegate) OVERRIDE { + if (delegate && Started()) { + ThreadedLayerAnimationElement::OnAbort(delegate); + delegate->SetTransformFromAnimation(ComputeCurrentTransform()); + } + } + + virtual void OnEnd(LayerAnimationDelegate* delegate) OVERRIDE { + delegate->SetTransformFromAnimation(computed_target_transform_); + } + + virtual scoped_ptr<cc::Animation> CreateCCAnimation() OVERRIDE { + scoped_ptr<cc::Animation> animation( + cc::Animation::Create(animation_curve_->Clone(), + animation_id(), + animation_group_id(), + cc::Animation::Transform)); + return animation.Pass(); + } + + virtual void OnGetTarget(TargetValue* target) const OVERRIDE { + target->transform = computed_target_transform_; + } + + private: + gfx::Transform ComputeCurrentTransform() const { + gfx::Transform base_current = gfx::Tween::ValueBetween( + gfx::Tween::CalculateValue(tween_type(), last_progressed_fraction()), + base_transform_, + base_target_); + return ComputeWithBaseTransform(effective_start_, base_current); + } + + gfx::Transform ComputeWithBaseTransform(gfx::Transform start, + gfx::Transform target) const { + gfx::Transform to_return(gfx::Transform::kSkipInitialization); + bool success = target.GetInverse(&to_return); + DCHECK(success) << "Target transform must be invertible."; + + to_return.PreconcatTransform(start); + return to_return; + } + + static AnimatableProperties GetProperties() { + AnimatableProperties properties; + properties.insert(LayerAnimationElement::TRANSFORM); + return properties; + } + + template <typename T> + static T CheckAndCast(const LayerAnimationElement* element) { + const AnimatableProperties& properties = element->properties(); + DCHECK(properties.find(TRANSFORM) != properties.end()); + return static_cast<T>(element); + } + + gfx::Transform effective_start_; + gfx::Transform computed_target_transform_; + + const gfx::Transform base_transform_; + gfx::Transform base_target_; + + scoped_ptr<cc::AnimationCurve> animation_curve_; + + const ThreadedTransformTransition* const uninverted_transition_; + + DISALLOW_COPY_AND_ASSIGN(InverseTransformTransition); +}; + } // namespace // LayerAnimationElement::TargetValue ------------------------------------------ @@ -595,12 +722,23 @@ LayerAnimationElement::LayerAnimationElement( : first_frame_(true), properties_(properties), duration_(GetEffectiveDuration(duration)), - tween_type_(Tween::LINEAR), + tween_type_(gfx::Tween::LINEAR), animation_id_(cc::AnimationIdProvider::NextAnimationId()), animation_group_id_(0), last_progressed_fraction_(0.0) { } +LayerAnimationElement::LayerAnimationElement( + const LayerAnimationElement &element) + : first_frame_(element.first_frame_), + properties_(element.properties_), + duration_(element.duration_), + tween_type_(element.tween_type_), + animation_id_(cc::AnimationIdProvider::NextAnimationId()), + animation_group_id_(element.animation_group_id_), + last_progressed_fraction_(element.last_progressed_fraction_) { +} + LayerAnimationElement::~LayerAnimationElement() { } @@ -634,7 +772,7 @@ bool LayerAnimationElement::Progress(base::TimeTicks now, base::TimeDelta elapsed = now - effective_start_time_; if ((duration_ > base::TimeDelta()) && (elapsed < duration_)) t = elapsed.InMillisecondsF() / duration_.InMillisecondsF(); - need_draw = OnProgress(Tween::CalculateValue(tween_type_, t), delegate); + need_draw = OnProgress(gfx::Tween::CalculateValue(tween_type_, t), delegate); first_frame_ = t == 1.0; last_progressed_fraction_ = t; return need_draw; @@ -729,6 +867,19 @@ LayerAnimationElement* LayerAnimationElement::CreateTransformElement( } // static +LayerAnimationElement* LayerAnimationElement::CreateInverseTransformElement( + const gfx::Transform& base_transform, + const LayerAnimationElement* uninverted_transition) { + return new InverseTransformTransition(base_transform, uninverted_transition); +} + +// static +LayerAnimationElement* LayerAnimationElement::CloneInverseTransformElement( + const LayerAnimationElement* other) { + return InverseTransformTransition::Clone(other); +} + +// static LayerAnimationElement* LayerAnimationElement::CreateInterpolatedTransformElement( InterpolatedTransform* interpolated_transform, diff --git a/chromium/ui/compositor/layer_animation_element.h b/chromium/ui/compositor/layer_animation_element.h index c5949d35e21..0c8a075cb0e 100644 --- a/chromium/ui/compositor/layer_animation_element.h +++ b/chromium/ui/compositor/layer_animation_element.h @@ -11,8 +11,8 @@ #include "cc/animation/animation.h" #include "cc/animation/animation_events.h" #include "third_party/skia/include/core/SkColor.h" -#include "ui/base/animation/tween.h" #include "ui/compositor/compositor_export.h" +#include "ui/gfx/animation/tween.h" #include "ui/gfx/rect.h" #include "ui/gfx/transform.h" @@ -57,6 +57,7 @@ class COMPOSITOR_EXPORT LayerAnimationElement { LayerAnimationElement(const AnimatableProperties& properties, base::TimeDelta duration); + virtual ~LayerAnimationElement(); // Creates an element that transitions to the given transform. The caller owns @@ -65,6 +66,19 @@ class COMPOSITOR_EXPORT LayerAnimationElement { const gfx::Transform& transform, base::TimeDelta duration); + // Creates an element that counters a transition to the given transform. + // This element maintains the invariant uninverted_transition->at(t) * + // this->at(t) == base_transform * this->at(t_start) for any t. The caller + // owns the return value. + static LayerAnimationElement* CreateInverseTransformElement( + const gfx::Transform& base_transform, + const LayerAnimationElement* uninverted_transition); + + + // Duplicates elements as created by CreateInverseTransformElement. + static LayerAnimationElement* CloneInverseTransformElement( + const LayerAnimationElement* other); + // Creates an element that transitions to another in a way determined by an // interpolated transform. The element accepts ownership of the interpolated // transform. NB: at every step, the interpolated transform clobbers the @@ -168,8 +182,8 @@ class COMPOSITOR_EXPORT LayerAnimationElement { // Whether this element animates on the compositor thread. virtual bool IsThreaded() const; - Tween::Type tween_type() const { return tween_type_; } - void set_tween_type(Tween::Type tween_type) { tween_type_ = tween_type; } + gfx::Tween::Type tween_type() const { return tween_type_; } + void set_tween_type(gfx::Tween::Type tween_type) { tween_type_ = tween_type; } // Each LayerAnimationElement has a unique animation_id. Elements belonging // to sequences that are supposed to start together have the same @@ -178,6 +192,8 @@ class COMPOSITOR_EXPORT LayerAnimationElement { int animation_group_id() const { return animation_group_id_; } void set_animation_group_id(int id) { animation_group_id_ = id; } + base::TimeDelta duration() const { return duration_; } + // The fraction of the animation that has been completed after the last // call made to {Progress, ProgressToEnd}. double last_progressed_fraction() const { return last_progressed_fraction_; } @@ -190,11 +206,11 @@ class COMPOSITOR_EXPORT LayerAnimationElement { virtual void OnGetTarget(TargetValue* target) const = 0; virtual void OnAbort(LayerAnimationDelegate* delegate) = 0; - base::TimeDelta duration() const { return duration_; } - // Actually start the animation, dispatching to another thread if needed. virtual void RequestEffectiveStart(LayerAnimationDelegate* delegate); + LayerAnimationElement(const LayerAnimationElement& element); + private: // For debugging purposes, we sometimes alter the duration we actually use. // For example, during tests we often set duration = 0, and it is sometimes @@ -208,14 +224,14 @@ class COMPOSITOR_EXPORT LayerAnimationElement { // When the animation actually started, taking into account queueing delays. base::TimeTicks effective_start_time_; const base::TimeDelta duration_; - Tween::Type tween_type_; + gfx::Tween::Type tween_type_; const int animation_id_; int animation_group_id_; double last_progressed_fraction_; - DISALLOW_COPY_AND_ASSIGN(LayerAnimationElement); + DISALLOW_ASSIGN(LayerAnimationElement); }; } // namespace ui diff --git a/chromium/ui/compositor/layer_animation_element_unittest.cc b/chromium/ui/compositor/layer_animation_element_unittest.cc index 2701200c014..8871a2c9f5e 100644 --- a/chromium/ui/compositor/layer_animation_element_unittest.cc +++ b/chromium/ui/compositor/layer_animation_element_unittest.cc @@ -10,6 +10,7 @@ #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/compositor/layer_animation_delegate.h" +#include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/compositor/test/test_layer_animation_delegate.h" #include "ui/compositor/test/test_utils.h" #include "ui/gfx/rect.h" @@ -23,7 +24,7 @@ namespace { // that the element can be reused after it completes. TEST(LayerAnimationElementTest, TransformElement) { TestLayerAnimationDelegate delegate; - gfx::Transform start_transform, target_transform, middle_transform; + gfx::Transform start_transform, target_transform; start_transform.Rotate(-30.0); target_transform.Rotate(30.0); base::TimeTicks start_time; @@ -65,6 +66,68 @@ TEST(LayerAnimationElementTest, TransformElement) { CheckApproximatelyEqual(target_transform, target_value.transform); } +// Ensures that duration is copied correctly. +TEST(LayerAnimationElementTest, InverseElementDurationNoScale) { + gfx::Transform transform; + base::TimeDelta delta; + + scoped_ptr<LayerAnimationElement> base_element( + LayerAnimationElement::CreateTransformElement(transform, delta)); + + scoped_ptr<LayerAnimationElement> inverse_element( + LayerAnimationElement::CreateInverseTransformElement(transform, + base_element.get())); + EXPECT_EQ(base_element->duration(), inverse_element->duration()); +} + +// Ensures that duration is copied correctly and not double scaled. +TEST(LayerAnimationElementTest, InverseElementDurationScaled) { + gfx::Transform transform; + base::TimeDelta delta; + + ScopedAnimationDurationScaleMode faster_duration( + ScopedAnimationDurationScaleMode::FAST_DURATION); + scoped_ptr<LayerAnimationElement> base_element( + LayerAnimationElement::CreateTransformElement(transform, delta)); + + scoped_ptr<LayerAnimationElement> inverse_element( + LayerAnimationElement::CreateInverseTransformElement(transform, + base_element.get())); + EXPECT_EQ(base_element->duration(), inverse_element->duration()); +} + +// Ensures that the GetTargetTransform() method works as intended. +TEST(LayerAnimationElementTest, InverseElementTargetCalculation) { + base::TimeTicks start_time; + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); + start_time += delta; + + gfx::Transform identity, transform; + + transform.Scale3d(2.0, 2.0, 2.0); + + scoped_ptr<LayerAnimationElement> base_element( + LayerAnimationElement::CreateTransformElement(transform, delta)); + scoped_ptr<LayerAnimationElement> inverse_element( + LayerAnimationElement::CreateInverseTransformElement(identity, + base_element.get())); + + base_element->set_requested_start_time(start_time); + inverse_element->set_requested_start_time(start_time); + + TestLayerAnimationDelegate delegate; + delegate.SetTransformFromAnimation(transform); + + base_element->Start(&delegate, 1); + inverse_element->Start(&delegate, 1); + LayerAnimationElement::TargetValue target; + inverse_element->GetTargetValue(&target); + + EXPECT_TRUE(target.transform.IsIdentity()) + << "Target should be identity such that the initial 2x scale from the start" + << " carries over at end when parent is doubled."; +} + // Check that the bounds element progresses the delegate as expected and // that the element can be reused after it completes. TEST(LayerAnimationElementTest, BoundsElement) { @@ -303,7 +366,7 @@ TEST(LayerAnimationElementTest, AbortOpacityElement) { LayerAnimationElement::CreateOpacityElement(target, delta)); // Choose a non-linear Tween type. - Tween::Type tween_type = Tween::EASE_IN; + gfx::Tween::Type tween_type = gfx::Tween::EASE_IN; element->set_tween_type(tween_type); delegate.SetOpacityFromAnimation(start); @@ -324,7 +387,7 @@ TEST(LayerAnimationElementTest, AbortOpacityElement) { // Since the element has started, it should update the delegate when // aborted. element->Abort(&delegate); - EXPECT_FLOAT_EQ(Tween::CalculateValue(tween_type, 0.5), + EXPECT_FLOAT_EQ(gfx::Tween::CalculateValue(tween_type, 0.5), delegate.GetOpacityForAnimation()); } @@ -342,7 +405,7 @@ TEST(LayerAnimationElementTest, AbortTransformElement) { LayerAnimationElement::CreateTransformElement(target_transform, delta)); // Choose a non-linear Tween type. - Tween::Type tween_type = Tween::EASE_IN; + gfx::Tween::Type tween_type = gfx::Tween::EASE_IN; element->set_tween_type(tween_type); delegate.SetTransformFromAnimation(start_transform); @@ -364,7 +427,7 @@ TEST(LayerAnimationElementTest, AbortTransformElement) { // aborted. element->Abort(&delegate); target_transform.Blend(start_transform, - Tween::CalculateValue(tween_type, 0.5)); + gfx::Tween::CalculateValue(tween_type, 0.5)); CheckApproximatelyEqual(target_transform, delegate.GetTransformForAnimation()); } diff --git a/chromium/ui/compositor/layer_animation_sequence.cc b/chromium/ui/compositor/layer_animation_sequence.cc index 371e5409219..f336035851a 100644 --- a/chromium/ui/compositor/layer_animation_sequence.cc +++ b/chromium/ui/compositor/layer_animation_sequence.cc @@ -8,6 +8,7 @@ #include <iterator> #include "base/debug/trace_event.h" +#include "cc/animation/animation_id_provider.h" #include "ui/compositor/layer_animation_delegate.h" #include "ui/compositor/layer_animation_element.h" #include "ui/compositor/layer_animation_observer.h" @@ -76,8 +77,10 @@ void LayerAnimationSequence::Progress(base::TimeTicks now, } if (is_cyclic_ || last_element_ < elements_.size()) { - if (!elements_[current_index]->Started()) + if (!elements_[current_index]->Started()) { + animation_group_id_ = cc::AnimationIdProvider::NextGroupId(); elements_[current_index]->Start(delegate, animation_group_id_); + } if (elements_[current_index]->Progress(now, delegate)) redraw_required = true; last_progressed_fraction_ = @@ -239,6 +242,18 @@ void LayerAnimationSequence::OnAnimatorDestroyed() { } } +size_t LayerAnimationSequence::size() const { + return elements_.size(); +} + +LayerAnimationElement* LayerAnimationSequence::FirstElement() const { + if (elements_.empty()) { + return NULL; + } + + return elements_[0].get(); +} + void LayerAnimationSequence::NotifyScheduled() { FOR_EACH_OBSERVER(LayerAnimationObserver, observers_, @@ -257,7 +272,7 @@ void LayerAnimationSequence::NotifyAborted() { OnLayerAnimationAborted(this)); } -LayerAnimationElement* LayerAnimationSequence::CurrentElement() { +LayerAnimationElement* LayerAnimationSequence::CurrentElement() const { if (elements_.empty()) return NULL; diff --git a/chromium/ui/compositor/layer_animation_sequence.h b/chromium/ui/compositor/layer_animation_sequence.h index 838c6b98841..854785ae150 100644 --- a/chromium/ui/compositor/layer_animation_sequence.h +++ b/chromium/ui/compositor/layer_animation_sequence.h @@ -102,6 +102,8 @@ class COMPOSITOR_EXPORT LayerAnimationSequence bool IsFirstElementThreaded() const; // Used to identify groups of sequences that are supposed to start together. + // Once started, used to identify the sequence that owns a particular + // threaded animation. int animation_group_id() const { return animation_group_id_; } void set_animation_group_id(int id) { animation_group_id_ = id; } @@ -123,6 +125,10 @@ class COMPOSITOR_EXPORT LayerAnimationSequence // by this sequence. Returns 0.0 if no elements have been progressed. double last_progressed_fraction() const { return last_progressed_fraction_; } + size_t size() const; + + LayerAnimationElement* FirstElement() const; + private: friend class LayerAnimatorTestController; @@ -141,7 +147,7 @@ class COMPOSITOR_EXPORT LayerAnimationSequence void NotifyAborted(); // The currently animating element. - LayerAnimationElement* CurrentElement(); + LayerAnimationElement* CurrentElement() const; // The union of all the properties modified by all elements in the sequence. LayerAnimationElement::AnimatableProperties properties_; @@ -164,6 +170,9 @@ class COMPOSITOR_EXPORT LayerAnimationSequence bool waiting_for_group_start_; // Identifies groups of sequences that are supposed to start together. + // Also used to identify the owner of a particular threaded animation; any + // in-progress threaded animation owned by this sequence will have this + // group id. int animation_group_id_; // These parties are notified when layer animations end. diff --git a/chromium/ui/compositor/layer_animation_sequence_unittest.cc b/chromium/ui/compositor/layer_animation_sequence_unittest.cc index fe70601f15d..3b4591762b0 100644 --- a/chromium/ui/compositor/layer_animation_sequence_unittest.cc +++ b/chromium/ui/compositor/layer_animation_sequence_unittest.cc @@ -82,8 +82,8 @@ TEST(LayerAnimationSequenceTest, SingleThreadedElement) { LayerAnimationElement::CreateOpacityElement(target, delta)); for (int i = 0; i < 2; ++i) { - int group_id = 1; - sequence.set_animation_group_id(group_id); + int starting_group_id = 1; + sequence.set_animation_group_id(starting_group_id); start_time = effective_start + delta; sequence.set_start_time(start_time); delegate.SetOpacityFromAnimation(start); @@ -94,7 +94,7 @@ TEST(LayerAnimationSequenceTest, SingleThreadedElement) { sequence.OnThreadedAnimationStarted(cc::AnimationEvent( cc::AnimationEvent::Started, 0, - group_id, + sequence.animation_group_id(), cc::Animation::Opacity, (effective_start - base::TimeTicks()).InSecondsF())); sequence.Progress(effective_start + delta/2, &delegate); @@ -139,8 +139,8 @@ TEST(LayerAnimationSequenceTest, MultipleElement) { LayerAnimationElement::CreateTransformElement(target_transform, delta)); for (int i = 0; i < 2; ++i) { - int group_id = 1; - sequence.set_animation_group_id(group_id); + int starting_group_id = 1; + sequence.set_animation_group_id(starting_group_id); start_time = opacity_effective_start + 4 * delta; sequence.set_start_time(start_time); delegate.SetOpacityFromAnimation(start_opacity); @@ -150,10 +150,11 @@ TEST(LayerAnimationSequenceTest, MultipleElement) { sequence.Progress(start_time, &delegate); EXPECT_FLOAT_EQ(0.0, sequence.last_progressed_fraction()); opacity_effective_start = start_time + delta; + EXPECT_EQ(starting_group_id, sequence.animation_group_id()); sequence.OnThreadedAnimationStarted(cc::AnimationEvent( cc::AnimationEvent::Started, 0, - group_id, + sequence.animation_group_id(), cc::Animation::Opacity, (opacity_effective_start - base::TimeTicks()).InSecondsF())); sequence.Progress(opacity_effective_start + delta/2, &delegate); @@ -180,10 +181,11 @@ TEST(LayerAnimationSequenceTest, MultipleElement) { delegate.GetTransformForAnimation()); EXPECT_FLOAT_EQ(0.0, sequence.last_progressed_fraction()); transform_effective_start = opacity_effective_start + 3 * delta; + EXPECT_NE(starting_group_id, sequence.animation_group_id()); sequence.OnThreadedAnimationStarted(cc::AnimationEvent( cc::AnimationEvent::Started, 0, - group_id, + sequence.animation_group_id(), cc::Animation::Transform, (transform_effective_start - base::TimeTicks()).InSecondsF())); sequence.Progress(transform_effective_start + delta/2, &delegate); diff --git a/chromium/ui/compositor/layer_animator.cc b/chromium/ui/compositor/layer_animator.cc index 4b1e9812232..c287574bbb8 100644 --- a/chromium/ui/compositor/layer_animator.cc +++ b/chromium/ui/compositor/layer_animator.cc @@ -8,12 +8,12 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "cc/animation/animation_id_provider.h" -#include "ui/base/animation/animation_container.h" #include "ui/compositor/compositor.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animation_delegate.h" #include "ui/compositor/layer_animation_observer.h" #include "ui/compositor/layer_animation_sequence.h" +#include "ui/gfx/animation/animation_container.h" #define SAFE_INVOKE_VOID(function, running_anim, ...) \ if (running_anim.is_sequence_alive()) \ @@ -37,10 +37,10 @@ const int kDefaultTransitionDurationMs = 120; const int kTimerIntervalMs = 10; // Returns the AnimationContainer we're added to. -ui::AnimationContainer* GetAnimationContainer() { - static ui::AnimationContainer* container = NULL; +gfx::AnimationContainer* GetAnimationContainer() { + static gfx::AnimationContainer* container = NULL; if (!container) { - container = new AnimationContainer(); + container = new gfx::AnimationContainer(); container->AddRef(); } return container; @@ -54,7 +54,7 @@ LayerAnimator::LayerAnimator(base::TimeDelta transition_duration) : delegate_(NULL), preemption_strategy_(IMMEDIATELY_SET_NEW_TARGET), transition_duration_(transition_duration), - tween_type_(Tween::LINEAR), + tween_type_(gfx::Tween::LINEAR), is_started_(false), disable_timer_for_test_(false), adding_animations_(false) { diff --git a/chromium/ui/compositor/layer_animator.h b/chromium/ui/compositor/layer_animator.h index 7d6392e940f..5fe0d5c1896 100644 --- a/chromium/ui/compositor/layer_animator.h +++ b/chromium/ui/compositor/layer_animator.h @@ -13,18 +13,18 @@ #include "base/memory/ref_counted.h" #include "base/observer_list.h" #include "base/time/time.h" -#include "ui/base/animation/animation_container_element.h" -#include "ui/base/animation/tween.h" #include "ui/compositor/compositor_export.h" #include "ui/compositor/layer_animation_element.h" +#include "ui/gfx/animation/animation_container_element.h" +#include "ui/gfx/animation/tween.h" namespace gfx { +class Animation; class Rect; class Transform; } namespace ui { -class Animation; class Layer; class LayerAnimationSequence; class LayerAnimationDelegate; @@ -41,7 +41,8 @@ class ScopedLayerAnimationSettings; // by holding a reference to itself for the duration of methods for which it // must guarantee that |this| is valid. class COMPOSITOR_EXPORT LayerAnimator - : public AnimationContainerElement, public base::RefCounted<LayerAnimator> { + : public gfx::AnimationContainerElement, + public base::RefCounted<LayerAnimator> { public: enum PreemptionStrategy { IMMEDIATELY_SET_NEW_TARGET, @@ -171,8 +172,8 @@ class COMPOSITOR_EXPORT LayerAnimator // This determines how implicit animations will be tweened. This has no // effect on animations that are explicitly started or scheduled. The default // is Tween::LINEAR. - void set_tween_type(Tween::Type tween_type) { tween_type_ = tween_type; } - Tween::Type tween_type() const { return tween_type_; } + void set_tween_type(gfx::Tween::Type tween_type) { tween_type_ = tween_type; } + gfx::Tween::Type tween_type() const { return tween_type_; } // For testing purposes only. void set_disable_timer_for_test(bool disable_timer) { @@ -320,7 +321,7 @@ class COMPOSITOR_EXPORT LayerAnimator base::TimeDelta transition_duration_; // The default tween type for implicit transitions - Tween::Type tween_type_; + gfx::Tween::Type tween_type_; // Used for coordinating the starting of animations. base::TimeTicks last_step_time_; diff --git a/chromium/ui/compositor/layer_animator_unittest.cc b/chromium/ui/compositor/layer_animator_unittest.cc index 8b4d792bf7f..b01a1c32165 100644 --- a/chromium/ui/compositor/layer_animator_unittest.cc +++ b/chromium/ui/compositor/layer_animator_unittest.cc @@ -10,6 +10,7 @@ #include "base/strings/stringprintf.h" #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/compositor/layer.h" #include "ui/compositor/layer_animation_delegate.h" #include "ui/compositor/layer_animation_element.h" #include "ui/compositor/layer_animation_sequence.h" @@ -22,6 +23,8 @@ #include "ui/gfx/rect.h" #include "ui/gfx/transform.h" +using gfx::AnimationContainerElement; + namespace ui { namespace { @@ -112,7 +115,6 @@ class DeletingLayerAnimationObserver : public LayerAnimationObserver { private: LayerAnimator* animator_; - LayerAnimationSequence* sequence_; DISALLOW_COPY_AND_ASSIGN(DeletingLayerAnimationObserver); }; @@ -1764,13 +1766,13 @@ TEST(LayerAnimatorTest, ObserverReleasedBeforeAnimationSequenceEnds) { animator->StartAnimation(sequence); // |observer| should be attached to |sequence|. - EXPECT_EQ(static_cast<size_t>(1), sequence->observers_.size()); + EXPECT_TRUE(sequence->observers_.might_have_observers()); // Now, release |observer| observer.reset(); // And |sequence| should no longer be attached to |observer|. - EXPECT_EQ(static_cast<size_t>(0), sequence->observers_.size()); + EXPECT_FALSE(sequence->observers_.might_have_observers()); } TEST(LayerAnimatorTest, ObserverAttachedAfterAnimationStarted) { @@ -2376,4 +2378,33 @@ TEST(LayerAnimatorTest, TestSetterRespectEnqueueStrategy) { EXPECT_EQ(start_opacity, delegate.GetOpacityForAnimation()); } +TEST(LayerAnimatorTest, TestScopedCounterAnimation) { + Layer parent, child; + parent.Add(&child); + + gfx::Transform parent_begin, parent_end; + + parent_end.Scale3d(2.0, 0.5, 1.0); + + // Parent animates from identity to the end value. The counter animation will + // start at the end value and animate back to identity. + gfx::Transform child_begin(parent_end); + + child.SetTransform(child_begin); + parent.SetTransform(parent_begin); + + EXPECT_FALSE(child.GetAnimator()->is_animating()); + + ScopedLayerAnimationSettings settings(parent.GetAnimator()); + settings.SetInverselyAnimatedBaseLayer(&parent); + settings.AddInverselyAnimatedLayer(&child); + + parent.SetTransform(parent_end); + + EXPECT_TRUE(child.GetAnimator()->is_animating()); + EXPECT_TRUE(child.GetTargetTransform().IsIdentity()) + << child.GetTargetTransform().ToString(); + +} + } // namespace ui diff --git a/chromium/ui/compositor/run_all_unittests.cc b/chromium/ui/compositor/run_all_unittests.cc index 52bb2fad611..f2f7251391e 100644 --- a/chromium/ui/compositor/run_all_unittests.cc +++ b/chromium/ui/compositor/run_all_unittests.cc @@ -2,8 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/bind.h" +#include "base/test/unit_test_launcher.h" #include "ui/compositor/test/test_suite.h" int main(int argc, char** argv) { - return ui::test::CompositorTestSuite(argc, argv).Run(); + ui::test::CompositorTestSuite test_suite(argc, argv); + + return base::LaunchUnitTests( + argc, argv, base::Bind(&ui::test::CompositorTestSuite::Run, + base::Unretained(&test_suite))); } diff --git a/chromium/ui/compositor/scoped_layer_animation_settings.cc b/chromium/ui/compositor/scoped_layer_animation_settings.cc index b45d94c65b7..b5bad673f60 100644 --- a/chromium/ui/compositor/scoped_layer_animation_settings.cc +++ b/chromium/ui/compositor/scoped_layer_animation_settings.cc @@ -4,7 +4,9 @@ #include "ui/compositor/scoped_layer_animation_settings.h" +#include "ui/compositor/layer.h" #include "ui/compositor/layer_animation_observer.h" +#include "ui/compositor/layer_animation_sequence.h" #include "ui/compositor/layer_animator.h" namespace { @@ -15,12 +17,74 @@ const int kDefaultTransitionDurationMs = 200; namespace ui { +// InvertingObserver ----------------------------------------------------------- +class InvertingObserver : public ImplicitAnimationObserver { + public: + InvertingObserver() + : base_layer_(NULL) { + } + + virtual ~InvertingObserver() {} + + void SetLayer(Layer* base_layer) { base_layer_ = base_layer; } + + Layer* layer() { return base_layer_; } + + void AddInverselyAnimatedLayer(Layer* inverse_layer) { + inverse_layers_.push_back(inverse_layer); + } + + virtual void OnImplicitAnimationsCompleted() OVERRIDE {} + + virtual void OnLayerAnimationScheduled( + LayerAnimationSequence* sequence) OVERRIDE { + DCHECK(base_layer_ != NULL) + << "Must set base layer with ScopedLayerAnimationSettings::" + << "SetInverslyAnimatedBaseLayer"; + gfx::Transform base_transform = base_layer_->transform(); + scoped_ptr<LayerAnimationElement> inverse = GetInverseElement(sequence, + base_transform); + + for (std::vector<Layer*>::const_iterator i = + inverse_layers_.begin(); i != inverse_layers_.end(); ++i) { + (*i)->GetAnimator()->StartAnimation(new LayerAnimationSequence( + LayerAnimationElement::CloneInverseTransformElement( + inverse.get()))); + } + } + private: + scoped_ptr<LayerAnimationElement> GetInverseElement( + LayerAnimationSequence* sequence, + gfx::Transform base) const { + const size_t expected_size = 1; + DCHECK_EQ(expected_size, sequence->size()) << + "Inverse supported only for single element sequences."; + + LayerAnimationElement* element = sequence->FirstElement(); + LayerAnimationElement::AnimatableProperties transform_property; + transform_property.insert(LayerAnimationElement::TRANSFORM); + DCHECK(transform_property == element->properties()) + << "Only transform animations are currently invertible."; + + scoped_ptr<LayerAnimationElement> to_return( + LayerAnimationElement::CreateInverseTransformElement(base, element)); + return to_return.Pass(); + } + + Layer* base_layer_; + // child layers + std::vector<Layer*> inverse_layers_; +}; + + +// ScoperLayerAnimationSettings ------------------------------------------------ ScopedLayerAnimationSettings::ScopedLayerAnimationSettings( LayerAnimator* animator) : animator_(animator), old_transition_duration_(animator->transition_duration_), old_tween_type_(animator->tween_type()), - old_preemption_strategy_(animator->preemption_strategy()) { + old_preemption_strategy_(animator->preemption_strategy()), + inverse_observer_(new InvertingObserver()) { SetTransitionDuration( base::TimeDelta::FromMilliseconds(kDefaultTransitionDurationMs)); } @@ -35,6 +99,10 @@ ScopedLayerAnimationSettings::~ScopedLayerAnimationSettings() { animator_->observers_.RemoveObserver(*i); (*i)->SetActive(true); } + + if (inverse_observer_->layer()) { + animator_->observers_.RemoveObserver(inverse_observer_.get()); + } } void ScopedLayerAnimationSettings::AddObserver( @@ -52,11 +120,11 @@ base::TimeDelta ScopedLayerAnimationSettings::GetTransitionDuration() const { return animator_->transition_duration_; } -void ScopedLayerAnimationSettings::SetTweenType(Tween::Type tween_type) { +void ScopedLayerAnimationSettings::SetTweenType(gfx::Tween::Type tween_type) { animator_->set_tween_type(tween_type); } -Tween::Type ScopedLayerAnimationSettings::GetTweenType() const { +gfx::Tween::Type ScopedLayerAnimationSettings::GetTweenType() const { return animator_->tween_type(); } @@ -70,4 +138,18 @@ ScopedLayerAnimationSettings::GetPreemptionStrategy() const { return animator_->preemption_strategy(); } +void ScopedLayerAnimationSettings::SetInverselyAnimatedBaseLayer(Layer* base) { + if (inverse_observer_->layer() && !base) { + animator_->RemoveObserver(inverse_observer_.get()); + } else if (base && !(inverse_observer_->layer())) { + animator_->AddObserver(inverse_observer_.get()); + } + inverse_observer_->SetLayer(base); +} + +void ScopedLayerAnimationSettings::AddInverselyAnimatedLayer( + Layer* inverse_layer) { + inverse_observer_->AddInverselyAnimatedLayer(inverse_layer); +} + } // namespace ui diff --git a/chromium/ui/compositor/scoped_layer_animation_settings.h b/chromium/ui/compositor/scoped_layer_animation_settings.h index 7f8e1c76340..e36b8532729 100644 --- a/chromium/ui/compositor/scoped_layer_animation_settings.h +++ b/chromium/ui/compositor/scoped_layer_animation_settings.h @@ -7,16 +7,18 @@ #include <set> +#include "base/memory/scoped_vector.h" #include "base/time/time.h" -#include "ui/base/animation/tween.h" #include "ui/compositor/compositor_export.h" #include "ui/compositor/layer_animator.h" +#include "ui/gfx/animation/tween.h" namespace ui { class ImplicitAnimationObserver; class LayerAnimationObserver; +class InvertingObserver; // Scoped settings allow you to temporarily change the animator's settings and // these changes are reverted when the object is destroyed. NOTE: when the @@ -32,18 +34,27 @@ class COMPOSITOR_EXPORT ScopedLayerAnimationSettings { void SetTransitionDuration(base::TimeDelta duration); base::TimeDelta GetTransitionDuration() const; - void SetTweenType(Tween::Type tween_type); - Tween::Type GetTweenType() const; + void SetTweenType(gfx::Tween::Type tween_type); + gfx::Tween::Type GetTweenType() const; void SetPreemptionStrategy(LayerAnimator::PreemptionStrategy strategy); LayerAnimator::PreemptionStrategy GetPreemptionStrategy() const; + // Sets the base layer whose animation will be countered. + void SetInverselyAnimatedBaseLayer(Layer* base); + + // Adds the layer to be counter-animated when a transform animation is + // scheduled on the animator_. Must call SetInverselyAnimatedBaseLayer with + // the layer associated with animator_ before animating. + void AddInverselyAnimatedLayer(Layer* inverse_layer); + private: LayerAnimator* animator_; base::TimeDelta old_transition_duration_; - Tween::Type old_tween_type_; + gfx::Tween::Type old_tween_type_; LayerAnimator::PreemptionStrategy old_preemption_strategy_; std::set<ImplicitAnimationObserver*> observers_; + scoped_ptr<InvertingObserver> inverse_observer_; DISALLOW_COPY_AND_ASSIGN(ScopedLayerAnimationSettings); }; diff --git a/chromium/ui/compositor/test_web_graphics_context_3d.cc b/chromium/ui/compositor/test_web_graphics_context_3d.cc deleted file mode 100644 index d8febc9ca08..00000000000 --- a/chromium/ui/compositor/test_web_graphics_context_3d.cc +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright (c) 2012 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 "ui/compositor/test_web_graphics_context_3d.h" - -#include "ui/gl/gl_bindings.h" -#include "ui/gl/gl_context_stub.h" -#include "ui/gl/gl_surface_stub.h" - -namespace ui { - -TestWebGraphicsContext3D::TestWebGraphicsContext3D() - : next_texture_id_(1) {} - -TestWebGraphicsContext3D::~TestWebGraphicsContext3D() {} - -void TestWebGraphicsContext3D::Initialize() { - gl_surface_ = new gfx::GLSurfaceStub; - gl_context_ = new gfx::GLContextStub; - gl_context_->MakeCurrent(gl_surface_.get()); -} - -bool TestWebGraphicsContext3D::makeContextCurrent() { - return true; -} - -int TestWebGraphicsContext3D::width() { - return 0; -} - -int TestWebGraphicsContext3D::height() { - return 0; -} - -bool TestWebGraphicsContext3D::isContextLost() { - return false; -} - -void* TestWebGraphicsContext3D::mapBufferSubDataCHROMIUM( - WebKit::WGC3Denum target, - WebKit::WGC3Dintptr offset, - WebKit::WGC3Dsizeiptr size, - WebKit::WGC3Denum access) { - return 0; -} - -void* TestWebGraphicsContext3D::mapTexSubImage2DCHROMIUM( - WebKit::WGC3Denum target, - WebKit::WGC3Dint level, - WebKit::WGC3Dint xoffset, - WebKit::WGC3Dint yoffset, - WebKit::WGC3Dsizei width, - WebKit::WGC3Dsizei height, - WebKit::WGC3Denum format, - WebKit::WGC3Denum type, - WebKit::WGC3Denum access) { - return 0; -} - -WebKit::WebString TestWebGraphicsContext3D::getRequestableExtensionsCHROMIUM() { - return WebKit::WebString(); -} - -WebKit::WGC3Denum TestWebGraphicsContext3D::checkFramebufferStatus( - WebKit::WGC3Denum target) { - return GL_FRAMEBUFFER_COMPLETE; -} - -bool TestWebGraphicsContext3D::getActiveAttrib(WebKit::WebGLId program, - WebKit::WGC3Duint index, - ActiveInfo& info) { - return false; -} - -bool TestWebGraphicsContext3D::getActiveUniform(WebKit::WebGLId program, - WebKit::WGC3Duint index, - ActiveInfo& info) { - return false; -} - -WebKit::WGC3Dint TestWebGraphicsContext3D::getAttribLocation( - WebKit::WebGLId program, - const WebKit::WGC3Dchar* name) { - return 0; -} - -TestWebGraphicsContext3D::Attributes -TestWebGraphicsContext3D::getContextAttributes() { - return Attributes(); -} - -WebKit::WGC3Denum TestWebGraphicsContext3D::getError() { - return 0; -} - -void TestWebGraphicsContext3D::getIntegerv(WebKit::WGC3Denum pname, - WebKit::WGC3Dint* value) { - if (pname == GL_MAX_TEXTURE_SIZE) - *value = 1024; - else if (pname == GL_ACTIVE_TEXTURE) - *value = GL_TEXTURE0; -} - -void TestWebGraphicsContext3D::getProgramiv(WebKit::WebGLId program, - WebKit::WGC3Denum pname, - WebKit::WGC3Dint* value) { - if (pname == GL_LINK_STATUS) - *value = 1; -} - -WebKit::WebString TestWebGraphicsContext3D::getProgramInfoLog( - WebKit::WebGLId program) { - return WebKit::WebString(); -} - -void TestWebGraphicsContext3D::getShaderiv(WebKit::WebGLId shader, - WebKit::WGC3Denum pname, - WebKit::WGC3Dint* value) { - if (pname == GL_COMPILE_STATUS) - *value = 1; -} - -WebKit::WebString TestWebGraphicsContext3D::getShaderInfoLog( - WebKit::WebGLId shader) { - return WebKit::WebString(); -} - -WebKit::WebString TestWebGraphicsContext3D::getShaderSource( - WebKit::WebGLId shader) { - return WebKit::WebString(); -} - -WebKit::WebString TestWebGraphicsContext3D::getString(WebKit::WGC3Denum name) { - return WebKit::WebString(); -} - -WebKit::WGC3Dint TestWebGraphicsContext3D::getUniformLocation( - WebKit::WebGLId program, - const WebKit::WGC3Dchar* name) { - return 0; -} - -WebKit::WGC3Dsizeiptr TestWebGraphicsContext3D::getVertexAttribOffset( - WebKit::WGC3Duint index, - WebKit::WGC3Denum pname) { - return 0; -} - -WebKit::WGC3Dboolean TestWebGraphicsContext3D::isBuffer( - WebKit::WebGLId buffer) { - return false; -} - -WebKit::WGC3Dboolean TestWebGraphicsContext3D::isEnabled( - WebKit::WGC3Denum cap) { - return false; -} - -WebKit::WGC3Dboolean TestWebGraphicsContext3D::isFramebuffer( - WebKit::WebGLId framebuffer) { - return false; -} - -WebKit::WGC3Dboolean TestWebGraphicsContext3D::isProgram( - WebKit::WebGLId program) { - return false; -} - -WebKit::WGC3Dboolean TestWebGraphicsContext3D::isRenderbuffer( - WebKit::WebGLId renderbuffer) { - return false; -} - -WebKit::WGC3Dboolean TestWebGraphicsContext3D::isShader( - WebKit::WebGLId shader) { - return false; -} - -WebKit::WGC3Dboolean TestWebGraphicsContext3D::isTexture( - WebKit::WebGLId texture) { - return false; -} - -WebKit::WebGLId TestWebGraphicsContext3D::createBuffer() { - return 1; -} - -WebKit::WebGLId TestWebGraphicsContext3D::createFramebuffer() { - return 1; -} - -WebKit::WebGLId TestWebGraphicsContext3D::createProgram() { - return 1; -} - -WebKit::WebGLId TestWebGraphicsContext3D::createRenderbuffer() { - return 1; -} - -WebKit::WebGLId TestWebGraphicsContext3D::createShader( - WebKit::WGC3Denum value) { - return 1; -} - -WebKit::WebGLId TestWebGraphicsContext3D::createTexture() { - return next_texture_id_++; -} - -WebKit::WebGLId TestWebGraphicsContext3D::createQueryEXT() -{ - return 1; -} - -WebKit::WGC3Dboolean TestWebGraphicsContext3D::isQueryEXT(WebKit::WebGLId) -{ - return true; -} - -} // namespace ui diff --git a/chromium/ui/compositor/test_web_graphics_context_3d.h b/chromium/ui/compositor/test_web_graphics_context_3d.h deleted file mode 100644 index f7a96220a47..00000000000 --- a/chromium/ui/compositor/test_web_graphics_context_3d.h +++ /dev/null @@ -1,450 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef UI_COMPOSITOR_TEST_WEB_GRAPHICS_CONTEXT_3D_H_ -#define UI_COMPOSITOR_TEST_WEB_GRAPHICS_CONTEXT_3D_H_ - -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" -#include "third_party/WebKit/public/platform/WebString.h" -#include "ui/compositor/compositor_export.h" - -namespace gfx { -class GLContext; -class GLSurface; -} - -namespace ui { - -// WebGraphicsContext3D that does nothing. Suitable for testing. -class COMPOSITOR_EXPORT TestWebGraphicsContext3D : - public NON_EXPORTED_BASE(WebKit::WebGraphicsContext3D) { - public: - TestWebGraphicsContext3D(); - virtual ~TestWebGraphicsContext3D(); - - void Initialize(); - virtual bool makeContextCurrent(); - virtual int width(); - virtual int height(); - virtual void reshape(int width, int height) {} - virtual void prepareTexture() {} - virtual void postSubBufferCHROMIUM(int x, int y, int width, int height) {} - virtual void synthesizeGLError(WebKit::WGC3Denum value) {} - virtual bool isContextLost(); - virtual void* mapBufferSubDataCHROMIUM(WebKit::WGC3Denum target, - WebKit::WGC3Dintptr offset, - WebKit::WGC3Dsizeiptr size, - WebKit::WGC3Denum access); - virtual void unmapBufferSubDataCHROMIUM(const void* data) {} - virtual void* mapTexSubImage2DCHROMIUM(WebKit::WGC3Denum target, - WebKit::WGC3Dint level, - WebKit::WGC3Dint xoffset, - WebKit::WGC3Dint yoffset, - WebKit::WGC3Dsizei width, - WebKit::WGC3Dsizei height, - WebKit::WGC3Denum format, - WebKit::WGC3Denum type, - WebKit::WGC3Denum access); - virtual void unmapTexSubImage2DCHROMIUM(const void* data) {} - virtual void setVisibilityCHROMIUM(bool visible) {} - virtual void discardFramebufferEXT(WebKit::WGC3Denum target, - WebKit::WGC3Dsizei numAttachments, - const WebKit::WGC3Denum* attachments) {} - virtual void setMemoryAllocationChangedCallbackCHROMIUM( - WebGraphicsMemoryAllocationChangedCallbackCHROMIUM*) { } - virtual WebKit::WebString getRequestableExtensionsCHROMIUM(); - virtual void requestExtensionCHROMIUM(const char*) {} - virtual void blitFramebufferCHROMIUM(WebKit::WGC3Dint src_x0, - WebKit::WGC3Dint src_y0, - WebKit::WGC3Dint src_x1, - WebKit::WGC3Dint src_y1, - WebKit::WGC3Dint dst_x0, - WebKit::WGC3Dint dst_y0, - WebKit::WGC3Dint dst_x1, - WebKit::WGC3Dint dst_y1, - WebKit::WGC3Dbitfield mask, - WebKit::WGC3Denum filter) {} - virtual void renderbufferStorageMultisampleCHROMIUM( - WebKit::WGC3Denum target, - WebKit::WGC3Dsizei samples, - WebKit::WGC3Denum internalformat, - WebKit::WGC3Dsizei width, - WebKit::WGC3Dsizei height) {} - virtual void activeTexture(WebKit::WGC3Denum texture) {} - virtual void attachShader(WebKit::WebGLId program, WebKit::WebGLId shader) {} - virtual void bindAttribLocation(WebKit::WebGLId program, - WebKit::WGC3Duint index, - const WebKit::WGC3Dchar* name) {} - virtual void bindBuffer(WebKit::WGC3Denum target, WebKit::WebGLId buffer) {} - virtual void bindFramebuffer(WebKit::WGC3Denum target, - WebKit::WebGLId framebuffer) {} - virtual void bindRenderbuffer(WebKit::WGC3Denum target, - WebKit::WebGLId renderbuffer) {} - virtual void bindTexture(WebKit::WGC3Denum target, WebKit::WebGLId texture) {} - virtual void blendColor(WebKit::WGC3Dclampf red, - WebKit::WGC3Dclampf green, - WebKit::WGC3Dclampf blue, - WebKit::WGC3Dclampf alpha) {} - virtual void blendEquation(WebKit::WGC3Denum mode) {} - virtual void blendEquationSeparate(WebKit::WGC3Denum modeRGB, - WebKit::WGC3Denum modeAlpha) {} - virtual void blendFunc(WebKit::WGC3Denum sfactor, - WebKit::WGC3Denum dfactor) {} - virtual void blendFuncSeparate(WebKit::WGC3Denum src_rgb, - WebKit::WGC3Denum dst_rgb, - WebKit::WGC3Denum src_alpha, - WebKit::WGC3Denum dst_alpha) {} - virtual void bufferData(WebKit::WGC3Denum target, - WebKit::WGC3Dsizeiptr size, - const void* data, - WebKit::WGC3Denum usage) {} - virtual void bufferSubData(WebKit::WGC3Denum target, - WebKit::WGC3Dintptr offset, - WebKit::WGC3Dsizeiptr size, - const void* data) {} - virtual WebKit::WGC3Denum checkFramebufferStatus(WebKit::WGC3Denum target); - virtual void clear(WebKit::WGC3Dbitfield mask) {} - virtual void clearColor(WebKit::WGC3Dclampf red, - WebKit::WGC3Dclampf green, - WebKit::WGC3Dclampf blue, - WebKit::WGC3Dclampf alpha) {} - virtual void clearDepth(WebKit::WGC3Dclampf depth) {} - virtual void clearStencil(WebKit::WGC3Dint s) {} - virtual void colorMask(WebKit::WGC3Dboolean red, - WebKit::WGC3Dboolean green, - WebKit::WGC3Dboolean blue, - WebKit::WGC3Dboolean alpha) {} - virtual void compileShader(WebKit::WebGLId shader) {} - virtual void compressedTexImage2D(WebKit::WGC3Denum target, - WebKit::WGC3Dint level, - WebKit::WGC3Denum internalformat, - WebKit::WGC3Dsizei width, - WebKit::WGC3Dsizei height, - WebKit::WGC3Dint border, - WebKit::WGC3Dsizei imageSize, - const void* data) {} - virtual void compressedTexSubImage2D(WebKit::WGC3Denum target, - WebKit::WGC3Dint level, - WebKit::WGC3Dint xoffset, - WebKit::WGC3Dint yoffset, - WebKit::WGC3Dsizei width, - WebKit::WGC3Dsizei height, - WebKit::WGC3Denum format, - WebKit::WGC3Dsizei imageSize, - const void* data) {} - virtual void copyTexImage2D(WebKit::WGC3Denum target, - WebKit::WGC3Dint level, - WebKit::WGC3Denum internal_format, - WebKit::WGC3Dint x, - WebKit::WGC3Dint y, - WebKit::WGC3Dsizei width, - WebKit::WGC3Dsizei height, - WebKit::WGC3Dint border) {} - virtual void copyTexSubImage2D(WebKit::WGC3Denum target, - WebKit::WGC3Dint level, - WebKit::WGC3Dint xoffset, - WebKit::WGC3Dint yoffset, - WebKit::WGC3Dint x, - WebKit::WGC3Dint y, - WebKit::WGC3Dsizei width, - WebKit::WGC3Dsizei height) {} - virtual void cullFace(WebKit::WGC3Denum mode) {} - virtual void depthFunc(WebKit::WGC3Denum func) {} - virtual void depthMask(WebKit::WGC3Dboolean flag) {} - virtual void depthRange(WebKit::WGC3Dclampf z_near, - WebKit::WGC3Dclampf z_far) {} - virtual void detachShader(WebKit::WebGLId program, WebKit::WebGLId shader) {} - virtual void disable(WebKit::WGC3Denum cap) {} - virtual void disableVertexAttribArray(WebKit::WGC3Duint index) {} - virtual void drawArrays(WebKit::WGC3Denum mode, WebKit::WGC3Dint first, - WebKit::WGC3Dsizei count) {} - virtual void drawElements(WebKit::WGC3Denum mode, - WebKit::WGC3Dsizei count, - WebKit::WGC3Denum type, - WebKit::WGC3Dintptr offset) {} - virtual void enable(WebKit::WGC3Denum cap) {} - virtual void enableVertexAttribArray(WebKit::WGC3Duint index) {} - virtual void finish() {} - virtual void flush() {} - virtual void framebufferRenderbuffer(WebKit::WGC3Denum target, - WebKit::WGC3Denum attachment, - WebKit::WGC3Denum renderbuffertarget, - WebKit::WebGLId renderbuffer) {} - virtual void framebufferTexture2D(WebKit::WGC3Denum target, - WebKit::WGC3Denum attachment, - WebKit::WGC3Denum textarget, - WebKit::WebGLId texture, - WebKit::WGC3Dint level) {} - virtual void frontFace(WebKit::WGC3Denum mode) {} - virtual void generateMipmap(WebKit::WGC3Denum target) {} - virtual bool getActiveAttrib(WebKit::WebGLId program, - WebKit::WGC3Duint index, - ActiveInfo& info); - virtual bool getActiveUniform(WebKit::WebGLId program, - WebKit::WGC3Duint index, - ActiveInfo& info); - virtual void getAttachedShaders(WebKit::WebGLId program, - WebKit::WGC3Dsizei maxCount, - WebKit::WGC3Dsizei* count, - WebKit::WebGLId* shaders) {} - virtual WebKit::WGC3Dint getAttribLocation(WebKit::WebGLId program, - const WebKit::WGC3Dchar* name); - virtual void getBooleanv(WebKit::WGC3Denum pname, - WebKit::WGC3Dboolean* value) {} - virtual void getBufferParameteriv(WebKit::WGC3Denum target, - WebKit::WGC3Denum pname, - WebKit::WGC3Dint* value) {} - virtual Attributes getContextAttributes(); - virtual WebKit::WGC3Denum getError(); - virtual void getFloatv(WebKit::WGC3Denum pname, WebKit::WGC3Dfloat* value) {} - virtual void getFramebufferAttachmentParameteriv(WebKit::WGC3Denum target, - WebKit::WGC3Denum attachment, - WebKit::WGC3Denum pname, - WebKit::WGC3Dint* value) {} - virtual void getIntegerv(WebKit::WGC3Denum pname, WebKit::WGC3Dint* value); - virtual void getProgramiv(WebKit::WebGLId program, - WebKit::WGC3Denum pname, - WebKit::WGC3Dint* value); - virtual WebKit::WebString getProgramInfoLog(WebKit::WebGLId program); - virtual void getRenderbufferParameteriv(WebKit::WGC3Denum target, - WebKit::WGC3Denum pname, - WebKit::WGC3Dint* value) {} - virtual void getShaderiv(WebKit::WebGLId shader, - WebKit::WGC3Denum pname, - WebKit::WGC3Dint* value); - virtual WebKit::WebString getShaderInfoLog(WebKit::WebGLId shader); - virtual void getShaderPrecisionFormat(WebKit::WGC3Denum shaderType, - WebKit::WGC3Denum precisionType, - WebKit::WGC3Dint* range, - WebKit::WGC3Dint* precision) {} - virtual WebKit::WebString getShaderSource(WebKit::WebGLId shader); - virtual WebKit::WebString getString(WebKit::WGC3Denum name); - virtual void getTexParameterfv(WebKit::WGC3Denum target, - WebKit::WGC3Denum pname, - WebKit::WGC3Dfloat* value) {} - virtual void getTexParameteriv(WebKit::WGC3Denum target, - WebKit::WGC3Denum pname, - WebKit::WGC3Dint* value) {} - virtual void getUniformfv(WebKit::WebGLId program, - WebKit::WGC3Dint location, - WebKit::WGC3Dfloat* value) {} - virtual void getUniformiv(WebKit::WebGLId program, - WebKit::WGC3Dint location, - WebKit::WGC3Dint* value) {} - virtual WebKit::WGC3Dint getUniformLocation(WebKit::WebGLId program, - const WebKit::WGC3Dchar* name); - virtual void getVertexAttribfv(WebKit::WGC3Duint index, - WebKit::WGC3Denum pname, - WebKit::WGC3Dfloat* value) {} - virtual void getVertexAttribiv(WebKit::WGC3Duint index, - WebKit::WGC3Denum pname, - WebKit::WGC3Dint* value) {} - virtual WebKit::WGC3Dsizeiptr getVertexAttribOffset(WebKit::WGC3Duint index, - WebKit::WGC3Denum pname); - virtual void hint(WebKit::WGC3Denum target, WebKit::WGC3Denum mode) {} - virtual WebKit::WGC3Dboolean isBuffer(WebKit::WebGLId buffer); - virtual WebKit::WGC3Dboolean isEnabled(WebKit::WGC3Denum cap); - virtual WebKit::WGC3Dboolean isFramebuffer(WebKit::WebGLId framebuffer); - virtual WebKit::WGC3Dboolean isProgram(WebKit::WebGLId program); - virtual WebKit::WGC3Dboolean isRenderbuffer(WebKit::WebGLId renderbuffer); - virtual WebKit::WGC3Dboolean isShader(WebKit::WebGLId shader); - virtual WebKit::WGC3Dboolean isTexture(WebKit::WebGLId texture); - virtual void lineWidth(WebKit::WGC3Dfloat) {} - virtual void linkProgram(WebKit::WebGLId program) {} - virtual void pixelStorei(WebKit::WGC3Denum pname, WebKit::WGC3Dint param) {} - virtual void polygonOffset(WebKit::WGC3Dfloat factor, - WebKit::WGC3Dfloat units) {} - virtual void readPixels(WebKit::WGC3Dint x, - WebKit::WGC3Dint y, - WebKit::WGC3Dsizei width, - WebKit::WGC3Dsizei height, - WebKit::WGC3Denum format, - WebKit::WGC3Denum type, - void* pixels) {} - virtual void releaseShaderCompiler() {} - virtual void renderbufferStorage(WebKit::WGC3Denum target, - WebKit::WGC3Denum internalformat, - WebKit::WGC3Dsizei width, - WebKit::WGC3Dsizei height) {} - virtual void sampleCoverage(WebKit::WGC3Dclampf value, - WebKit::WGC3Dboolean invert) {} - virtual void scissor(WebKit::WGC3Dint x, - WebKit::WGC3Dint y, - WebKit::WGC3Dsizei width, - WebKit::WGC3Dsizei height) {} - virtual void shaderSource(WebKit::WebGLId shader, - const WebKit::WGC3Dchar* string) {} - virtual void stencilFunc(WebKit::WGC3Denum func, - WebKit::WGC3Dint ref, - WebKit::WGC3Duint mask) {} - virtual void stencilFuncSeparate(WebKit::WGC3Denum face, - WebKit::WGC3Denum func, - WebKit::WGC3Dint ref, - WebKit::WGC3Duint mask) {} - virtual void stencilMask(WebKit::WGC3Duint mask) {} - virtual void stencilMaskSeparate(WebKit::WGC3Denum face, - WebKit::WGC3Duint mask) {} - virtual void stencilOp(WebKit::WGC3Denum fail, - WebKit::WGC3Denum zfail, - WebKit::WGC3Denum zpass) {} - virtual void stencilOpSeparate(WebKit::WGC3Denum face, - WebKit::WGC3Denum fail, - WebKit::WGC3Denum zfail, - WebKit::WGC3Denum zpass) {} - virtual void texImage2D(WebKit::WGC3Denum target, - WebKit::WGC3Dint level, - WebKit::WGC3Denum internal_format, - WebKit::WGC3Dsizei width, - WebKit::WGC3Dsizei height, - WebKit::WGC3Dint border, - WebKit::WGC3Denum format, - WebKit::WGC3Denum type, - const void* pixels) {} - virtual void texParameterf(WebKit::WGC3Denum target, - WebKit::WGC3Denum pname, - WebKit::WGC3Dfloat param) {} - virtual void texParameteri(WebKit::WGC3Denum target, - WebKit::WGC3Denum pname, - WebKit::WGC3Dint param) {} - virtual void texSubImage2D(WebKit::WGC3Denum target, - WebKit::WGC3Dint level, - WebKit::WGC3Dint xoffset, - WebKit::WGC3Dint yoffset, - WebKit::WGC3Dsizei width, - WebKit::WGC3Dsizei height, - WebKit::WGC3Denum format, - WebKit::WGC3Denum type, - const void* pixels) {} - virtual void uniform1f(WebKit::WGC3Dint location, WebKit::WGC3Dfloat x) {} - virtual void uniform1fv(WebKit::WGC3Dint location, - WebKit::WGC3Dsizei count, - const WebKit::WGC3Dfloat* v) {} - virtual void uniform1i(WebKit::WGC3Dint location, WebKit::WGC3Dint x) {} - virtual void uniform1iv(WebKit::WGC3Dint location, - WebKit::WGC3Dsizei count, - const WebKit::WGC3Dint* v) {} - virtual void uniform2f(WebKit::WGC3Dint location, - WebKit::WGC3Dfloat x, - WebKit::WGC3Dfloat y) {} - virtual void uniform2fv(WebKit::WGC3Dint location, - WebKit::WGC3Dsizei count, - const WebKit::WGC3Dfloat* v) {} - virtual void uniform2i(WebKit::WGC3Dint location, - WebKit::WGC3Dint x, - WebKit::WGC3Dint y) {} - virtual void uniform2iv(WebKit::WGC3Dint location, - WebKit::WGC3Dsizei count, - const WebKit::WGC3Dint* v) {} - virtual void uniform3f(WebKit::WGC3Dint location, - WebKit::WGC3Dfloat x, - WebKit::WGC3Dfloat y, - WebKit::WGC3Dfloat z) {} - virtual void uniform3fv(WebKit::WGC3Dint location, - WebKit::WGC3Dsizei count, - const WebKit::WGC3Dfloat* v) {} - virtual void uniform3i(WebKit::WGC3Dint location, - WebKit::WGC3Dint x, - WebKit::WGC3Dint y, - WebKit::WGC3Dint z) {} - virtual void uniform3iv(WebKit::WGC3Dint location, - WebKit::WGC3Dsizei count, - const WebKit::WGC3Dint* v) {} - virtual void uniform4f(WebKit::WGC3Dint location, - WebKit::WGC3Dfloat x, - WebKit::WGC3Dfloat y, - WebKit::WGC3Dfloat z, - WebKit::WGC3Dfloat w) {} - virtual void uniform4fv(WebKit::WGC3Dint location, - WebKit::WGC3Dsizei count, - const WebKit::WGC3Dfloat* v) {} - virtual void uniform4i(WebKit::WGC3Dint location, - WebKit::WGC3Dint x, - WebKit::WGC3Dint y, - WebKit::WGC3Dint z, - WebKit::WGC3Dint w) {} - virtual void uniform4iv(WebKit::WGC3Dint location, - WebKit::WGC3Dsizei count, - const WebKit::WGC3Dint* v) {} - virtual void uniformMatrix2fv(WebKit::WGC3Dint location, - WebKit::WGC3Dsizei count, - WebKit::WGC3Dboolean transpose, - const WebKit::WGC3Dfloat* value) {} - virtual void uniformMatrix3fv(WebKit::WGC3Dint location, - WebKit::WGC3Dsizei count, - WebKit::WGC3Dboolean transpose, - const WebKit::WGC3Dfloat* value) {} - virtual void uniformMatrix4fv(WebKit::WGC3Dint location, - WebKit::WGC3Dsizei count, - WebKit::WGC3Dboolean transpose, - const WebKit::WGC3Dfloat* value) {} - virtual void useProgram(WebKit::WebGLId program) {} - virtual void validateProgram(WebKit::WebGLId program) {} - virtual void vertexAttrib1f(WebKit::WGC3Duint index, WebKit::WGC3Dfloat x) {} - virtual void vertexAttrib1fv(WebKit::WGC3Duint index, - const WebKit::WGC3Dfloat* values) {} - virtual void vertexAttrib2f(WebKit::WGC3Duint index, - WebKit::WGC3Dfloat x, - WebKit::WGC3Dfloat y) {} - virtual void vertexAttrib2fv(WebKit::WGC3Duint index, - const WebKit::WGC3Dfloat* values) {} - virtual void vertexAttrib3f(WebKit::WGC3Duint index, - WebKit::WGC3Dfloat x, - WebKit::WGC3Dfloat y, - WebKit::WGC3Dfloat z) {} - virtual void vertexAttrib3fv(WebKit::WGC3Duint index, - const WebKit::WGC3Dfloat* values) {} - virtual void vertexAttrib4f(WebKit::WGC3Duint index, - WebKit::WGC3Dfloat x, - WebKit::WGC3Dfloat y, - WebKit::WGC3Dfloat z, - WebKit::WGC3Dfloat w) {} - virtual void vertexAttrib4fv(WebKit::WGC3Duint index, - const WebKit::WGC3Dfloat* values) {} - virtual void vertexAttribPointer(WebKit::WGC3Duint index, - WebKit::WGC3Dint size, - WebKit::WGC3Denum type, - WebKit::WGC3Dboolean normalized, - WebKit::WGC3Dsizei stride, - WebKit::WGC3Dintptr offset) {} - virtual void viewport(WebKit::WGC3Dint x, - WebKit::WGC3Dint y, - WebKit::WGC3Dsizei width, - WebKit::WGC3Dsizei height) {} - virtual WebKit::WebGLId createBuffer(); - virtual WebKit::WebGLId createFramebuffer(); - virtual WebKit::WebGLId createProgram(); - virtual WebKit::WebGLId createRenderbuffer(); - virtual WebKit::WebGLId createShader(WebKit::WGC3Denum value); - virtual WebKit::WebGLId createTexture(); - virtual void deleteBuffer(WebKit::WebGLId) {} - virtual void deleteFramebuffer(WebKit::WebGLId) {} - virtual void deleteProgram(WebKit::WebGLId) {} - virtual void deleteRenderbuffer(WebKit::WebGLId) {} - virtual void deleteShader(WebKit::WebGLId) {} - virtual void deleteTexture(WebKit::WebGLId) {} - virtual WebKit::WebGLId createQueryEXT(); - virtual void deleteQueryEXT(WebKit::WebGLId) {}; - virtual WebKit::WGC3Dboolean isQueryEXT(WebKit::WebGLId query); - virtual void beginQueryEXT(WebKit::WGC3Denum, WebKit::WebGLId) {} - virtual void endQueryEXT(WebKit::WGC3Denum) {} - virtual void getQueryivEXT(WebKit::WGC3Denum, - WebKit::WGC3Denum, - WebKit::WGC3Dint*) {} - virtual void getQueryObjectuivEXT(WebKit::WebGLId, - WebKit::WGC3Denum, - WebKit::WGC3Duint*) {} - - private: - scoped_refptr<gfx::GLContext> gl_context_; - scoped_refptr<gfx::GLSurface> gl_surface_; - unsigned next_texture_id_; - - DISALLOW_COPY_AND_ASSIGN(TestWebGraphicsContext3D); -}; - -} // namespace ui - -#endif // UI_COMPOSITOR_TEST_WEB_GRAPHICS_CONTEXT_3D_H_ diff --git a/chromium/ui/compositor/transform_animation_curve_adapter.cc b/chromium/ui/compositor/transform_animation_curve_adapter.cc index 96500b3de52..49feb6af746 100644 --- a/chromium/ui/compositor/transform_animation_curve_adapter.cc +++ b/chromium/ui/compositor/transform_animation_curve_adapter.cc @@ -7,7 +7,7 @@ namespace ui { TransformAnimationCurveAdapter::TransformAnimationCurveAdapter( - Tween::Type tween_type, + gfx::Tween::Type tween_type, gfx::Transform initial_value, gfx::Transform target_value, base::TimeDelta duration) @@ -47,8 +47,67 @@ gfx::Transform TransformAnimationCurveAdapter::GetValue( gfx::BlendDecomposedTransforms(&to_return, decomposed_target_value_, decomposed_initial_value_, - Tween::CalculateValue(tween_type_, progress)); + gfx::Tween::CalculateValue(tween_type_, + progress)); return gfx::ComposeTransform(to_return); } +bool TransformAnimationCurveAdapter::AnimatedBoundsForBox( + const gfx::BoxF& box, + gfx::BoxF* bounds) const { + // TODO(ajuma): Once cc::TransformOperation::BlendedBoundsForBox supports + // computing bounds for TransformOperationMatrix, use that to compute + // the bounds we need here. + return false; +} + +InverseTransformCurveAdapter::InverseTransformCurveAdapter( + TransformAnimationCurveAdapter base_curve, + gfx::Transform initial_value, + base::TimeDelta duration) + : base_curve_(base_curve), + initial_value_(initial_value), + duration_(duration) { + effective_initial_value_ = base_curve_.GetValue(0.0) * initial_value_; +} + +InverseTransformCurveAdapter::~InverseTransformCurveAdapter() { +} + +double InverseTransformCurveAdapter::Duration() const { + return duration_.InSeconds(); +} + +scoped_ptr<cc::AnimationCurve> InverseTransformCurveAdapter::Clone() const { + scoped_ptr<InverseTransformCurveAdapter> to_return( + new InverseTransformCurveAdapter(base_curve_, + initial_value_, + duration_)); + return to_return.PassAs<cc::AnimationCurve>(); +} + +gfx::Transform InverseTransformCurveAdapter::GetValue( + double t) const { + if (t <= 0.0) + return initial_value_; + + gfx::Transform base_transform = base_curve_.GetValue(t); + // Invert base + gfx::Transform to_return(gfx::Transform::kSkipInitialization); + bool is_invertible = base_transform.GetInverse(&to_return); + DCHECK(is_invertible); + + to_return.PreconcatTransform(effective_initial_value_); + return to_return; +} + +bool InverseTransformCurveAdapter::AnimatedBoundsForBox( + const gfx::BoxF& box, + gfx::BoxF* bounds) const { + // TODO(ajuma): Once cc::TransformOperation::BlendedBoundsForBox supports + // computing bounds for TransformOperationMatrix, use that to compute + // the bounds we need here. + return false; +} + } // namespace ui diff --git a/chromium/ui/compositor/transform_animation_curve_adapter.h b/chromium/ui/compositor/transform_animation_curve_adapter.h index 7b6bdcea52b..36861e46008 100644 --- a/chromium/ui/compositor/transform_animation_curve_adapter.h +++ b/chromium/ui/compositor/transform_animation_curve_adapter.h @@ -7,15 +7,17 @@ #include "base/time/time.h" #include "cc/animation/animation_curve.h" -#include "ui/base/animation/tween.h" +#include "ui/compositor/compositor_export.h" +#include "ui/gfx/animation/tween.h" #include "ui/gfx/transform.h" #include "ui/gfx/transform_util.h" namespace ui { -class TransformAnimationCurveAdapter :public cc::TransformAnimationCurve { +class COMPOSITOR_EXPORT TransformAnimationCurveAdapter + : public cc::TransformAnimationCurve { public: - TransformAnimationCurveAdapter(Tween::Type tween_type, + TransformAnimationCurveAdapter(gfx::Tween::Type tween_type, gfx::Transform intial_value, gfx::Transform target_value, base::TimeDelta duration); @@ -26,14 +28,42 @@ class TransformAnimationCurveAdapter :public cc::TransformAnimationCurve { virtual double Duration() const OVERRIDE; virtual scoped_ptr<AnimationCurve> Clone() const OVERRIDE; virtual gfx::Transform GetValue(double t) const OVERRIDE; + virtual bool AnimatedBoundsForBox(const gfx::BoxF& box, + gfx::BoxF* bounds) const OVERRIDE; private: - Tween::Type tween_type_; + gfx::Tween::Type tween_type_; gfx::Transform initial_value_; gfx::Transform target_value_; gfx::DecomposedTransform decomposed_initial_value_; gfx::DecomposedTransform decomposed_target_value_; base::TimeDelta duration_; + + DISALLOW_ASSIGN(TransformAnimationCurveAdapter); +}; + +class COMPOSITOR_EXPORT InverseTransformCurveAdapter + : public cc::TransformAnimationCurve { + public: + InverseTransformCurveAdapter(TransformAnimationCurveAdapter base_curve, + gfx::Transform initial_value, + base::TimeDelta duration); + + virtual ~InverseTransformCurveAdapter(); + + virtual double Duration() const OVERRIDE; + virtual scoped_ptr<AnimationCurve> Clone() const OVERRIDE; + virtual gfx::Transform GetValue(double t) const OVERRIDE; + virtual bool AnimatedBoundsForBox(const gfx::BoxF& box, + gfx::BoxF* bounds) const OVERRIDE; + + private: + TransformAnimationCurveAdapter base_curve_; + gfx::Transform initial_value_; + gfx::Transform effective_initial_value_; + base::TimeDelta duration_; + + DISALLOW_ASSIGN(InverseTransformCurveAdapter); }; } // namespace ui diff --git a/chromium/ui/compositor/transform_animation_curve_adapter_unittest.cc b/chromium/ui/compositor/transform_animation_curve_adapter_unittest.cc new file mode 100644 index 00000000000..b68e8626891 --- /dev/null +++ b/chromium/ui/compositor/transform_animation_curve_adapter_unittest.cc @@ -0,0 +1,59 @@ +// 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 "ui/compositor/transform_animation_curve_adapter.h" + +#include <sstream> + +#include "base/time/time.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/compositor/test/test_utils.h" + +namespace ui { + +namespace { + +// Check that the inverse transform curve gives the gives a transform that when +// applied on top of the parent transform gives the original transform +TEST(InverseTransformCurveAdapterTest, InversesTransform) { + gfx::Transform parent_start, parent_target; + parent_start.Scale(0.5, 3.0); + parent_start.Translate(-20.0, 30.0); + parent_target.Translate(0, 100); + + gfx::Transform child_transform; + child_transform.Rotate(-30.0); + + base::TimeDelta duration = base::TimeDelta::FromSeconds(1); + + const gfx::Transform effective_child_transform = + parent_start * child_transform; + + TransformAnimationCurveAdapter parent_curve(gfx::Tween::LINEAR, + parent_start, + parent_target, + duration); + + InverseTransformCurveAdapter child_curve(parent_curve, + child_transform, + duration); + static const int kSteps = 1000; + double step = 1.0 / kSteps; + for (int i = 0; i <= kSteps ; ++i) { + std::ostringstream message; + message << "Step " << i << " of " << kSteps; + SCOPED_TRACE(message.str()); + gfx::Transform progress_parent_transform = + parent_curve.GetValue(i*step); + gfx::Transform progress_child_transform = + child_curve.GetValue(i*step); + CheckApproximatelyEqual(effective_child_transform, + progress_parent_transform * + progress_child_transform); + } +} + +} // namespace + +} // namespace ui diff --git a/chromium/ui/base/events/OWNERS b/chromium/ui/events/OWNERS index b8e32c10903..b8e32c10903 100644 --- a/chromium/ui/base/events/OWNERS +++ b/chromium/ui/events/OWNERS diff --git a/chromium/ui/base/events/event.cc b/chromium/ui/events/event.cc index 02813108f7a..7c3e6d5021c 100644 --- a/chromium/ui/base/events/event.cc +++ b/chromium/ui/events/event.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/events/event.h" +#include "ui/events/event.h" #if defined(USE_X11) #include <X11/Xlib.h> @@ -13,15 +13,15 @@ #include "base/metrics/histogram.h" #include "base/strings/stringprintf.h" -#include "ui/base/events/event_utils.h" -#include "ui/base/keycodes/keyboard_code_conversion.h" +#include "ui/events/event_utils.h" +#include "ui/events/keycodes/keyboard_code_conversion.h" #include "ui/gfx/point3_f.h" #include "ui/gfx/point_conversions.h" #include "ui/gfx/transform.h" #include "ui/gfx/transform_util.h" #if defined(USE_X11) -#include "ui/base/keycodes/keyboard_code_conversion_x.h" +#include "ui/events/keycodes/keyboard_code_conversion_x.h" #endif namespace { @@ -36,7 +36,7 @@ base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) { #elif defined(OS_WIN) return event; #elif defined(USE_OZONE) - return event; + return NULL; #else NOTREACHED() << "Don't know how to copy base::NativeEvent for this platform"; @@ -284,7 +284,7 @@ void LocatedEvent::UpdateForRootTransform( const gfx::Transform& reversed_root_transform) { // Transform has to be done at root level. gfx::Point3F p(location_); - reversed_root_transform.TransformPoint(p); + reversed_root_transform.TransformPoint(&p); root_location_ = location_ = gfx::ToFlooredPoint(p.AsPointF()); } @@ -295,7 +295,7 @@ MouseEvent::MouseEvent(const base::NativeEvent& native_event) : LocatedEvent(native_event), changed_button_flags_( GetChangedMouseButtonFlagsFromNative(native_event)) { - if (type() == ET_MOUSE_PRESSED) + if (type() == ET_MOUSE_PRESSED || type() == ET_MOUSE_RELEASED) SetClickCount(GetRepeatCount(*this)); } @@ -345,6 +345,8 @@ bool MouseEvent::IsRepeatedClickEvent( int MouseEvent::GetRepeatCount(const MouseEvent& event) { int click_count = 1; if (last_click_event_) { + if (event.type() == ui::ET_MOUSE_RELEASED) + return last_click_event_->GetClickCount(); if (IsX11SendEventTrue(event.native_event())) click_count = last_click_event_->GetClickCount(); else if (IsRepeatedClickEvent(*last_click_event_, event)) @@ -362,7 +364,7 @@ int MouseEvent::GetRepeatCount(const MouseEvent& event) { MouseEvent* MouseEvent::last_click_event_ = NULL; int MouseEvent::GetClickCount() const { - if (type() != ET_MOUSE_PRESSED) + if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED) return 0; if (flags() & EF_IS_TRIPLE_CLICK) @@ -374,7 +376,7 @@ int MouseEvent::GetClickCount() const { } void MouseEvent::SetClickCount(int click_count) { - if (type() != ET_MOUSE_PRESSED) + if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED) return; DCHECK(click_count > 0); @@ -600,7 +602,11 @@ uint16 KeyEvent::GetUnmodifiedCharacter() const { } KeyEvent* KeyEvent::Copy() const { +#if defined(USE_OZONE) + KeyEvent* copy = new KeyEvent(*this); +#else KeyEvent* copy = new KeyEvent(::CopyNativeEvent(native_event()), is_char()); +#endif #if defined(USE_X11) copy->set_delete_native_event(true); #endif @@ -735,18 +741,6 @@ void ScrollEvent::Scale(const float factor) { y_offset_ordinal_ *= factor; } -void ScrollEvent::UpdateForRootTransform( - const gfx::Transform& inverted_root_transform) { - LocatedEvent::UpdateForRootTransform(inverted_root_transform); - gfx::DecomposedTransform decomp; - bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform); - DCHECK(success); - if (decomp.scale[0]) - x_offset_ordinal_ *= decomp.scale[0]; - if (decomp.scale[1]) - y_offset_ordinal_ *= decomp.scale[1]; -} - //////////////////////////////////////////////////////////////////////////////// // GestureEvent diff --git a/chromium/ui/base/events/event.h b/chromium/ui/events/event.h index 193e6e6a237..5c7582f7faf 100644 --- a/chromium/ui/base/events/event.h +++ b/chromium/ui/events/event.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_EVENTS_EVENT_H_ -#define UI_BASE_EVENTS_EVENT_H_ +#ifndef UI_EVENTS_EVENT_H_ +#define UI_EVENTS_EVENT_H_ #include "base/basictypes.h" #include "base/compiler_specific.h" @@ -11,11 +11,10 @@ #include "base/logging.h" #include "base/time/time.h" #include "ui/base/dragdrop/os_exchange_data.h" -#include "ui/base/events/event_constants.h" #include "ui/base/gestures/gesture_types.h" -#include "ui/base/keycodes/keyboard_codes.h" -#include "ui/base/latency_info.h" -#include "ui/base/ui_export.h" +#include "ui/events/event_constants.h" +#include "ui/events/keycodes/keyboard_codes.h" +#include "ui/events/latency_info.h" #include "ui/gfx/point.h" namespace gfx { @@ -25,7 +24,7 @@ class Transform; namespace ui { class EventTarget; -class UI_EXPORT Event { +class EVENTS_EXPORT Event { public: virtual ~Event(); @@ -220,8 +219,6 @@ class UI_EXPORT Event { void InitLatencyInfo(); private: - void operator=(const Event&); - // Safely initializes the native event members of this class. void Init(); void InitWithNativeEvent(const base::NativeEvent& native_event); @@ -240,13 +237,13 @@ class UI_EXPORT Event { EventResult result_; }; -class UI_EXPORT CancelModeEvent : public Event { +class EVENTS_EXPORT CancelModeEvent : public Event { public: CancelModeEvent(); virtual ~CancelModeEvent(); }; -class UI_EXPORT LocatedEvent : public Event { +class EVENTS_EXPORT LocatedEvent : public Event { public: // For testing. class TestApi : public Event::TestApi { @@ -313,7 +310,7 @@ class UI_EXPORT LocatedEvent : public Event { gfx::Point root_location_; }; -class UI_EXPORT MouseEvent : public LocatedEvent { +class EVENTS_EXPORT MouseEvent : public LocatedEvent { public: explicit MouseEvent(const base::NativeEvent& native_event); @@ -410,7 +407,7 @@ class UI_EXPORT MouseEvent : public LocatedEvent { class ScrollEvent; -class UI_EXPORT MouseWheelEvent : public MouseEvent { +class EVENTS_EXPORT MouseWheelEvent : public MouseEvent { public: // See |offset| for details. static const int kWheelDelta; @@ -444,7 +441,7 @@ class UI_EXPORT MouseWheelEvent : public MouseEvent { gfx::Vector2d offset_; }; -class UI_EXPORT TouchEvent : public LocatedEvent { +class EVENTS_EXPORT TouchEvent : public LocatedEvent { public: explicit TouchEvent(const base::NativeEvent& native_event); @@ -527,7 +524,7 @@ class UI_EXPORT TouchEvent : public LocatedEvent { float force_; }; -class UI_EXPORT KeyEvent : public Event { +class EVENTS_EXPORT KeyEvent : public Event { public: KeyEvent(const base::NativeEvent& native_event, bool is_char); @@ -587,7 +584,7 @@ class UI_EXPORT KeyEvent : public Event { // TranslatedKeyEvent(VKEY_SPACE) event. If the IME receives a KeyEvent and // it does consume the event, it might dispatch a // TranslatedKeyEvent(VKEY_PROCESSKEY) event as defined in the DOM spec. -class UI_EXPORT TranslatedKeyEvent : public KeyEvent { +class EVENTS_EXPORT TranslatedKeyEvent : public KeyEvent { public: TranslatedKeyEvent(const base::NativeEvent& native_event, bool is_char); @@ -602,7 +599,7 @@ class UI_EXPORT TranslatedKeyEvent : public KeyEvent { DISALLOW_COPY_AND_ASSIGN(TranslatedKeyEvent); }; -class UI_EXPORT DropTargetEvent : public LocatedEvent { +class EVENTS_EXPORT DropTargetEvent : public LocatedEvent { public: DropTargetEvent(const OSExchangeData& data, const gfx::Point& location, @@ -622,7 +619,7 @@ class UI_EXPORT DropTargetEvent : public LocatedEvent { DISALLOW_COPY_AND_ASSIGN(DropTargetEvent); }; -class UI_EXPORT ScrollEvent : public MouseEvent { +class EVENTS_EXPORT ScrollEvent : public MouseEvent { public: explicit ScrollEvent(const base::NativeEvent& native_event); template <class T> @@ -659,10 +656,6 @@ class UI_EXPORT ScrollEvent : public MouseEvent { float y_offset_ordinal() const { return y_offset_ordinal_; } int finger_count() const { return finger_count_; } - // Overridden from LocatedEvent. - virtual void UpdateForRootTransform( - const gfx::Transform& inverted_root_transform) OVERRIDE; - private: // Potential accelerated offsets. float x_offset_; @@ -674,7 +667,7 @@ class UI_EXPORT ScrollEvent : public MouseEvent { int finger_count_; }; -class UI_EXPORT GestureEvent : public LocatedEvent { +class EVENTS_EXPORT GestureEvent : public LocatedEvent { public: GestureEvent(EventType type, int x, @@ -710,10 +703,8 @@ class UI_EXPORT GestureEvent : public LocatedEvent { // This value is stored as a bitfield because the number of touch ids varies, // but we currently don't need more than 32 touches at a time. const unsigned int touch_ids_bitfield_; - - DISALLOW_COPY_AND_ASSIGN(GestureEvent); }; } // namespace ui -#endif // UI_BASE_EVENTS_EVENT_H_ +#endif // UI_EVENTS_EVENT_H_ diff --git a/chromium/ui/base/events/event_constants.h b/chromium/ui/events/event_constants.h index 2c04770ec88..6c0e9f71bc0 100644 --- a/chromium/ui/base/events/event_constants.h +++ b/chromium/ui/events/event_constants.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_EVENTS_EVENT_CONSTANTS_H_ -#define UI_BASE_EVENTS_EVENT_CONSTANTS_H_ +#ifndef UI_EVENTS_EVENT_CONSTANTS_H_ +#define UI_EVENTS_EVENT_CONSTANTS_H_ namespace ui { @@ -113,4 +113,4 @@ enum EventPhase { } // namespace ui -#endif // UI_BASE_EVENTS_EVENT_CONSTANTS_H_ +#endif // UI_EVENTS_EVENT_CONSTANTS_H_ diff --git a/chromium/ui/base/events/event_dispatcher.cc b/chromium/ui/events/event_dispatcher.cc index 06c857c2f29..b774b94dcf6 100644 --- a/chromium/ui/base/events/event_dispatcher.cc +++ b/chromium/ui/events/event_dispatcher.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/events/event_dispatcher.h" +#include "ui/events/event_dispatcher.h" #include <algorithm> diff --git a/chromium/ui/base/events/event_dispatcher.h b/chromium/ui/events/event_dispatcher.h index b9fd0dc79cd..ef8d6b1c5bb 100644 --- a/chromium/ui/base/events/event_dispatcher.h +++ b/chromium/ui/events/event_dispatcher.h @@ -2,20 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_EVENTS_EVENT_DISPATCHER_H_ -#define UI_BASE_EVENTS_EVENT_DISPATCHER_H_ +#ifndef UI_EVENTS_EVENT_DISPATCHER_H_ +#define UI_EVENTS_EVENT_DISPATCHER_H_ #include "base/auto_reset.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/events/event_target.h" -#include "ui/base/ui_export.h" +#include "ui/events/event.h" +#include "ui/events/event_constants.h" +#include "ui/events/event_target.h" +#include "ui/events/events_export.h" namespace ui { class EventDispatcher; -class UI_EXPORT EventDispatcherDelegate { +class EVENTS_EXPORT EventDispatcherDelegate { public: EventDispatcherDelegate(); virtual ~EventDispatcherDelegate(); @@ -42,7 +42,7 @@ class UI_EXPORT EventDispatcherDelegate { }; // Dispatches events to appropriate targets. -class UI_EXPORT EventDispatcher { +class EVENTS_EXPORT EventDispatcher { public: explicit EventDispatcher(EventDispatcherDelegate* delegate); virtual ~EventDispatcher(); @@ -77,4 +77,4 @@ class UI_EXPORT EventDispatcher { } // namespace ui -#endif // UI_BASE_EVENTS_EVENT_DISPATCHER_H_ +#endif // UI_EVENTS_EVENT_DISPATCHER_H_ diff --git a/chromium/ui/base/events/event_dispatcher_unittest.cc b/chromium/ui/events/event_dispatcher_unittest.cc index 41ab0487ee8..b0b3b8a5e38 100644 --- a/chromium/ui/base/events/event_dispatcher_unittest.cc +++ b/chromium/ui/events/event_dispatcher_unittest.cc @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/events/event_dispatcher.h" +#include "ui/events/event_dispatcher.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_utils.h" +#include "ui/events/event.h" +#include "ui/events/event_utils.h" namespace ui { diff --git a/chromium/ui/base/events/event_handler.cc b/chromium/ui/events/event_handler.cc index 99295b15c6e..243007a5553 100644 --- a/chromium/ui/base/events/event_handler.cc +++ b/chromium/ui/events/event_handler.cc @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/events/event_dispatcher.h" -#include "ui/base/events/event_handler.h" +#include "ui/events/event_handler.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" +#include "ui/events/event_dispatcher.h" namespace ui { diff --git a/chromium/ui/base/events/event_handler.h b/chromium/ui/events/event_handler.h index 6ecc3890e8e..088c3f84253 100644 --- a/chromium/ui/base/events/event_handler.h +++ b/chromium/ui/events/event_handler.h @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_EVENTS_EVENT_HANDLER_H_ -#define UI_BASE_EVENTS_EVENT_HANDLER_H_ +#ifndef UI_EVENTS_EVENT_HANDLER_H_ +#define UI_EVENTS_EVENT_HANDLER_H_ #include <stack> #include <vector> #include "base/basictypes.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/ui_export.h" +#include "ui/events/event_constants.h" +#include "ui/events/events_export.h" namespace ui { @@ -26,7 +26,7 @@ class TouchEvent; // Dispatches events to appropriate targets. The default implementations of // all of the specific handlers (e.g. OnKeyEvent, OnMouseEvent) do nothing. -class UI_EXPORT EventHandler { +class EVENTS_EXPORT EventHandler { public: EventHandler(); virtual ~EventHandler(); @@ -63,4 +63,4 @@ typedef std::vector<EventHandler*> EventHandlerList; } // namespace ui -#endif // UI_BASE_EVENTS_EVENT_HANDLER_H_ +#endif // UI_EVENTS_EVENT_HANDLER_H_ diff --git a/chromium/ui/base/events/event_target.cc b/chromium/ui/events/event_target.cc index 7ef69c80bbe..9aa53902ca9 100644 --- a/chromium/ui/base/events/event_target.cc +++ b/chromium/ui/events/event_target.cc @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/events/event_target.h" +#include "ui/events/event_target.h" #include <algorithm> #include "base/logging.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" namespace ui { diff --git a/chromium/ui/base/events/event_target.h b/chromium/ui/events/event_target.h index 6961b73cac6..39671e23bde 100644 --- a/chromium/ui/base/events/event_target.h +++ b/chromium/ui/events/event_target.h @@ -2,19 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_EVENTS_EVENT_TARGET_H_ -#define UI_BASE_EVENTS_EVENT_TARGET_H_ +#ifndef UI_EVENTS_EVENT_TARGET_H_ +#define UI_EVENTS_EVENT_TARGET_H_ #include "base/basictypes.h" #include "base/compiler_specific.h" -#include "ui/base/events/event_handler.h" -#include "ui/base/ui_export.h" +#include "ui/events/event_handler.h" +#include "ui/events/events_export.h" namespace ui { class EventDispatcher; -class UI_EXPORT EventTarget : public EventHandler { +class EVENTS_EXPORT EventTarget : public EventHandler { public: typedef std::vector<EventTarget*> EventTargets; @@ -105,4 +105,4 @@ class UI_EXPORT EventTarget : public EventHandler { } // namespace ui -#endif // UI_BASE_EVENTS_EVENT_TARGET_H_ +#endif // UI_EVENTS_EVENT_TARGET_H_ diff --git a/chromium/ui/base/events/event_unittest.cc b/chromium/ui/events/event_unittest.cc index d55ac9241cf..418c0695336 100644 --- a/chromium/ui/base/events/event_unittest.cc +++ b/chromium/ui/events/event_unittest.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" #if defined(USE_X11) #include <X11/Xlib.h> diff --git a/chromium/ui/base/events/event_utils.cc b/chromium/ui/events/event_utils.cc index ac09854bbfb..5504e4cb399 100644 --- a/chromium/ui/base/events/event_utils.cc +++ b/chromium/ui/events/event_utils.cc @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/events/event_utils.h" +#include "ui/events/event_utils.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" namespace ui { diff --git a/chromium/ui/base/events/event_utils.h b/chromium/ui/events/event_utils.h index d57ced90ac6..bcf1213855e 100644 --- a/chromium/ui/base/events/event_utils.h +++ b/chromium/ui/events/event_utils.h @@ -2,13 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_EVENTS_EVENT_UTILS_H_ -#define UI_BASE_EVENTS_EVENT_UTILS_H_ +#ifndef UI_EVENTS_EVENT_UTILS_H_ +#define UI_EVENTS_EVENT_UTILS_H_ #include "base/event_types.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/event_constants.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/native_widget_types.h" +#include "ui/events/events_export.h" #if defined(OS_WIN) #include <windows.h> @@ -28,30 +29,31 @@ namespace ui { class Event; // Updates the list of devices for cached properties. -UI_EXPORT void UpdateDeviceList(); +EVENTS_EXPORT void UpdateDeviceList(); // Get the EventType from a native event. -UI_EXPORT EventType EventTypeFromNative(const base::NativeEvent& native_event); +EVENTS_EXPORT EventType EventTypeFromNative( + const base::NativeEvent& native_event); // Get the EventFlags from a native event. -UI_EXPORT int EventFlagsFromNative(const base::NativeEvent& native_event); +EVENTS_EXPORT int EventFlagsFromNative(const base::NativeEvent& native_event); // Get the timestamp from a native event. -UI_EXPORT base::TimeDelta EventTimeFromNative( +EVENTS_EXPORT base::TimeDelta EventTimeFromNative( const base::NativeEvent& native_event); // Create a timestamp based on the current time. -UI_EXPORT base::TimeDelta EventTimeForNow(); +EVENTS_EXPORT base::TimeDelta EventTimeForNow(); // Get the location from a native event. The coordinate system of the resultant // |Point| has the origin at top-left of the "root window". The nature of // this "root window" and how it maps to platform-specific drawing surfaces is // defined in ui/aura/root_window.* and ui/aura/root_window_host*. -UI_EXPORT gfx::Point EventLocationFromNative( +EVENTS_EXPORT gfx::Point EventLocationFromNative( const base::NativeEvent& native_event); // Gets the location in native system coordinate space. -UI_EXPORT gfx::Point EventSystemLocationFromNative( +EVENTS_EXPORT gfx::Point EventSystemLocationFromNative( const base::NativeEvent& native_event); #if defined(USE_X11) @@ -59,43 +61,44 @@ UI_EXPORT gfx::Point EventSystemLocationFromNative( // does not take into account any remapping (e.g. using xmodmap), while the // button reported in master events do. This is a utility function to always // return the mapped button. -UI_EXPORT int EventButtonFromNative(const base::NativeEvent& native_event); +EVENTS_EXPORT int EventButtonFromNative(const base::NativeEvent& native_event); #endif // Returns the KeyboardCode from a native event. -UI_EXPORT KeyboardCode KeyboardCodeFromNative( +EVENTS_EXPORT KeyboardCode KeyboardCodeFromNative( const base::NativeEvent& native_event); // Returns true if the message is a mouse event. -UI_EXPORT bool IsMouseEvent(const base::NativeEvent& native_event); +EVENTS_EXPORT bool IsMouseEvent(const base::NativeEvent& native_event); // Returns the flags of the button that changed during a press/release. -UI_EXPORT int GetChangedMouseButtonFlagsFromNative( +EVENTS_EXPORT int GetChangedMouseButtonFlagsFromNative( const base::NativeEvent& native_event); // Gets the mouse wheel offsets from a native event. -UI_EXPORT gfx::Vector2d GetMouseWheelOffset( +EVENTS_EXPORT gfx::Vector2d GetMouseWheelOffset( const base::NativeEvent& native_event); // Gets the touch id from a native event. -UI_EXPORT int GetTouchId(const base::NativeEvent& native_event); +EVENTS_EXPORT int GetTouchId(const base::NativeEvent& native_event); // Clear the touch id from bookkeeping if it is a release/cancel event. -UI_EXPORT void ClearTouchIdIfReleased(const base::NativeEvent& native_event); +EVENTS_EXPORT void ClearTouchIdIfReleased( + const base::NativeEvent& native_event); // Gets the radius along the X/Y axis from a native event. Default is 1.0. -UI_EXPORT float GetTouchRadiusX(const base::NativeEvent& native_event); -UI_EXPORT float GetTouchRadiusY(const base::NativeEvent& native_event); +EVENTS_EXPORT float GetTouchRadiusX(const base::NativeEvent& native_event); +EVENTS_EXPORT float GetTouchRadiusY(const base::NativeEvent& native_event); // Gets the angle of the major axis away from the X axis. Default is 0.0. -UI_EXPORT float GetTouchAngle(const base::NativeEvent& native_event); +EVENTS_EXPORT float GetTouchAngle(const base::NativeEvent& native_event); // Gets the force from a native_event. Normalized to be [0, 1]. Default is 0.0. -UI_EXPORT float GetTouchForce(const base::NativeEvent& native_event); +EVENTS_EXPORT float GetTouchForce(const base::NativeEvent& native_event); // Gets the fling velocity from a native event. is_cancel is set to true if // this was a tap down, intended to stop an ongoing fling. -UI_EXPORT bool GetFlingData(const base::NativeEvent& native_event, +EVENTS_EXPORT bool GetFlingData(const base::NativeEvent& native_event, float* vx, float* vy, float* vx_ordinal, @@ -104,50 +107,50 @@ UI_EXPORT bool GetFlingData(const base::NativeEvent& native_event, // Returns whether this is a scroll event and optionally gets the amount to be // scrolled. |x_offset|, |y_offset| and |finger_count| can be NULL. -UI_EXPORT bool GetScrollOffsets(const base::NativeEvent& native_event, +EVENTS_EXPORT bool GetScrollOffsets(const base::NativeEvent& native_event, float* x_offset, float* y_offset, float* x_offset_ordinal, float* y_offset_ordinal, int* finger_count); -UI_EXPORT bool GetGestureTimes(const base::NativeEvent& native_event, +EVENTS_EXPORT bool GetGestureTimes(const base::NativeEvent& native_event, double* start_time, double* end_time); // Enable/disable natural scrolling for touchpads. -UI_EXPORT void SetNaturalScroll(bool enabled); +EVENTS_EXPORT void SetNaturalScroll(bool enabled); // In natural scrolling enabled for touchpads? -UI_EXPORT bool IsNaturalScrollEnabled(); +EVENTS_EXPORT bool IsNaturalScrollEnabled(); // Was this event generated by a touchpad device? // The caller is responsible for ensuring that this is a mouse/touchpad event // before calling this function. -UI_EXPORT bool IsTouchpadEvent(const base::NativeEvent& event); +EVENTS_EXPORT bool IsTouchpadEvent(const base::NativeEvent& event); // Returns true if event is noop. -UI_EXPORT bool IsNoopEvent(const base::NativeEvent& event); +EVENTS_EXPORT bool IsNoopEvent(const base::NativeEvent& event); // Creates and returns no-op event. -UI_EXPORT base::NativeEvent CreateNoopEvent(); +EVENTS_EXPORT base::NativeEvent CreateNoopEvent(); #if defined(OS_WIN) -UI_EXPORT int GetModifiersFromACCEL(const ACCEL& accel); -UI_EXPORT int GetModifiersFromKeyState(); +EVENTS_EXPORT int GetModifiersFromACCEL(const ACCEL& accel); +EVENTS_EXPORT int GetModifiersFromKeyState(); // Returns true if |message| identifies a mouse event that was generated as the // result of a touch event. -UI_EXPORT bool IsMouseEventFromTouch(UINT message); +EVENTS_EXPORT bool IsMouseEventFromTouch(UINT message); #endif // Returns true if default post-target handling was canceled for |event| after // its dispatch to its target. -UI_EXPORT bool EventCanceledDefaultHandling(const Event& event); +EVENTS_EXPORT bool EventCanceledDefaultHandling(const Event& event); // Registers a custom event type. -UI_EXPORT int RegisterCustomEventType(); +EVENTS_EXPORT int RegisterCustomEventType(); } // namespace ui -#endif // UI_BASE_EVENTS_EVENT_UTILS_H_ +#endif // UI_EVENTS_EVENT_UTILS_H_ diff --git a/chromium/ui/events/events_export.h b/chromium/ui/events/events_export.h new file mode 100644 index 00000000000..84d96a6a5f7 --- /dev/null +++ b/chromium/ui/events/events_export.h @@ -0,0 +1,33 @@ +// Copyright (c) 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. + +#ifndef UI_EVENTS_EVENTS_EXPORT_H_ +#define UI_EVENTS_EVENTS_EXPORT_H_ + +// TODO(beng): remove include once events dependencies have been corrected. + +#include "ui/base/ui_export.h" + +#if defined(COMPONENT_BUILD) +#if defined(WIN32) + +#if defined(UI_IMPLEMENTATION) +#define EVENTS_EXPORT __declspec(dllexport) +#else +#define EVENTS_EXPORT __declspec(dllimport) +#endif // defined(UI_IMPLEMENTATION) + +#else // defined(WIN32) +#if defined(UI_IMPLEMENTATION) +#define EVENTS_EXPORT __attribute__((visibility("default"))) +#else +#define EVENTS_EXPORT +#endif +#endif + +#else // defined(COMPONENT_BUILD) +#define EVENTS_EXPORT +#endif + +#endif // UI_EVENTS_EVENTS_EXPORT_H_ diff --git a/chromium/ui/base/keycodes/keyboard_code_conversion.cc b/chromium/ui/events/keycodes/keyboard_code_conversion.cc index 1a4d92aa4cf..a812b51db3f 100644 --- a/chromium/ui/base/keycodes/keyboard_code_conversion.cc +++ b/chromium/ui/events/keycodes/keyboard_code_conversion.cc @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/keycodes/keyboard_code_conversion.h" +#include "ui/events/keycodes/keyboard_code_conversion.h" -#include "ui/base/events/event_constants.h" +#include "ui/events/event_constants.h" namespace ui { diff --git a/chromium/ui/base/keycodes/keyboard_code_conversion.h b/chromium/ui/events/keycodes/keyboard_code_conversion.h index afc7aad2b89..87baf882814 100644 --- a/chromium/ui/base/keycodes/keyboard_code_conversion.h +++ b/chromium/ui/events/keycodes/keyboard_code_conversion.h @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_KEYCODES_KEYBOARD_CODE_CONVERSION_H_ -#define UI_BASE_KEYCODES_KEYBOARD_CODE_CONVERSION_H_ +#ifndef UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_H_ +#define UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_H_ #include "base/basictypes.h" -#include "ui/base/keycodes/keyboard_codes.h" -#include "ui/base/ui_export.h" +#include "ui/events/events_export.h" +#include "ui/events/keycodes/keyboard_codes.h" namespace ui { @@ -31,8 +31,8 @@ namespace ui { // correct character. That's why we can use XLookupString() function to get // the correct text generated by a X key event (See how is GetCharacter() // implemented in event_x.cc). -UI_EXPORT uint16 GetCharacterFromKeyCode(KeyboardCode key_code, int flags); +EVENTS_EXPORT uint16 GetCharacterFromKeyCode(KeyboardCode key_code, int flags); } // namespace ui -#endif // UI_BASE_KEYCODES_KEYBOARD_CODE_CONVERSION_H_ +#endif // UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_H_ diff --git a/chromium/ui/base/keycodes/keyboard_code_conversion_android.cc b/chromium/ui/events/keycodes/keyboard_code_conversion_android.cc index 42f2cc7cbe1..fa0ed31c341 100644 --- a/chromium/ui/base/keycodes/keyboard_code_conversion_android.cc +++ b/chromium/ui/events/keycodes/keyboard_code_conversion_android.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/keycodes/keyboard_code_conversion_android.h" +#include "ui/events/keycodes/keyboard_code_conversion_android.h" #include <android/keycodes.h> diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_android.h b/chromium/ui/events/keycodes/keyboard_code_conversion_android.h new file mode 100644 index 00000000000..f064393b760 --- /dev/null +++ b/chromium/ui/events/keycodes/keyboard_code_conversion_android.h @@ -0,0 +1,17 @@ +// 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. + +#ifndef UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_ANDROID_H_ +#define UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_ANDROID_H_ + +#include "ui/events/events_export.h" +#include "ui/events/keycodes/keyboard_codes_posix.h" + +namespace ui { + +EVENTS_EXPORT KeyboardCode KeyboardCodeFromAndroidKeyCode(int keycode); + +} // namespace ui + +#endif // UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_ANDROID_H_ diff --git a/chromium/ui/base/keycodes/keyboard_code_conversion_gtk.cc b/chromium/ui/events/keycodes/keyboard_code_conversion_gtk.cc index 0d3fcae60b2..9a396534e20 100644 --- a/chromium/ui/base/keycodes/keyboard_code_conversion_gtk.cc +++ b/chromium/ui/events/keycodes/keyboard_code_conversion_gtk.cc @@ -33,7 +33,7 @@ // WindowsKeyCodeForGdkKeyCode is copied from platform/gtk/KeyEventGtk.cpp -#include "ui/base/keycodes/keyboard_code_conversion_gtk.h" +#include "ui/events/keycodes/keyboard_code_conversion_gtk.h" #include <gdk/gdk.h> #include <gdk/gdkkeysyms.h> @@ -41,8 +41,8 @@ #include "base/basictypes.h" #include "build/build_config.h" -#include "ui/base/keycodes/keyboard_code_conversion_x.h" -#include "ui/base/keycodes/keyboard_codes_posix.h" +#include "ui/events/keycodes/keyboard_code_conversion_x.h" +#include "ui/events/keycodes/keyboard_codes_posix.h" namespace ui { diff --git a/chromium/ui/base/keycodes/keyboard_code_conversion_gtk.h b/chromium/ui/events/keycodes/keyboard_code_conversion_gtk.h index 3593d0c6c62..c9b6a8dd63b 100644 --- a/chromium/ui/base/keycodes/keyboard_code_conversion_gtk.h +++ b/chromium/ui/events/keycodes/keyboard_code_conversion_gtk.h @@ -33,25 +33,25 @@ // WindowsKeyCodeForGdkKeyCode is copied from platform/gtk/KeyEventGtk.cpp -#ifndef UI_BASE_KEYCODES_KEYBOARD_CODE_CONVERSION_GTK_H_ -#define UI_BASE_KEYCODES_KEYBOARD_CODE_CONVERSION_GTK_H_ +#ifndef UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_GTK_H_ +#define UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_GTK_H_ -#include "ui/base/keycodes/keyboard_codes_posix.h" -#include "ui/base/ui_export.h" +#include "ui/events/events_export.h" +#include "ui/events/keycodes/keyboard_codes_posix.h" typedef struct _GdkEventKey GdkEventKey; namespace ui { -UI_EXPORT KeyboardCode WindowsKeyCodeForGdkKeyCode(int keycode); +EVENTS_EXPORT KeyboardCode WindowsKeyCodeForGdkKeyCode(int keycode); -UI_EXPORT int GdkKeyCodeForWindowsKeyCode(KeyboardCode keycode, bool shift); +EVENTS_EXPORT int GdkKeyCodeForWindowsKeyCode(KeyboardCode keycode, bool shift); // For WebKit DRT testing: simulate the native keycode for the given // input |keycode|. Return the native keycode. -UI_EXPORT int GdkNativeKeyCodeForWindowsKeyCode(KeyboardCode keycode, +EVENTS_EXPORT int GdkNativeKeyCodeForWindowsKeyCode(KeyboardCode keycode, bool shift); } // namespace ui -#endif // UI_BASE_KEYCODES_KEYBOARD_CODE_CONVERSION_GTK_H_ +#endif // UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_GTK_H_ diff --git a/chromium/ui/base/keycodes/keyboard_code_conversion_mac.h b/chromium/ui/events/keycodes/keyboard_code_conversion_mac.h index b0e97790541..d7c05b0072c 100644 --- a/chromium/ui/base/keycodes/keyboard_code_conversion_mac.h +++ b/chromium/ui/events/keycodes/keyboard_code_conversion_mac.h @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_KEYCODES_KEYBOARD_CODE_CONVERSION_MAC_H_ -#define UI_BASE_KEYCODES_KEYBOARD_CODE_CONVERSION_MAC_H_ +#ifndef UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_MAC_H_ +#define UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_MAC_H_ #import <Cocoa/Cocoa.h> #include "base/basictypes.h" -#include "ui/base/keycodes/keyboard_codes_posix.h" -#include "ui/base/ui_export.h" +#include "ui/events/events_export.h" +#include "ui/events/keycodes/keyboard_codes_posix.h" namespace ui { @@ -25,7 +25,7 @@ namespace ui { // -1 will be returned if the keycode can't be converted. // This function is mainly for simulating keyboard events in unit tests. // See |KeyboardCodeFromNSEvent| for reverse conversion. -UI_EXPORT int MacKeyCodeForWindowsKeyCode(KeyboardCode keycode, +EVENTS_EXPORT int MacKeyCodeForWindowsKeyCode(KeyboardCode keycode, NSUInteger flags, unichar* character, unichar* characterIgnoringModifiers); @@ -34,8 +34,8 @@ UI_EXPORT int MacKeyCodeForWindowsKeyCode(KeyboardCode keycode, // third_party/WebKit/Source/web/mac/WebInputEventFactory.mm // Converts |event| into a |KeyboardCode|. The mapping is not direct as the Mac // has a different notion of key codes. -UI_EXPORT KeyboardCode KeyboardCodeFromNSEvent(NSEvent* event); +EVENTS_EXPORT KeyboardCode KeyboardCodeFromNSEvent(NSEvent* event); } // namespace ui -#endif // UI_BASE_KEYCODES_KEYBOARD_CODE_CONVERSION_MAC_H_ +#endif // UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_MAC_H_ diff --git a/chromium/ui/base/keycodes/keyboard_code_conversion_mac.mm b/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm index 2f8c2110e92..ed50392f84a 100644 --- a/chromium/ui/base/keycodes/keyboard_code_conversion_mac.mm +++ b/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ui/base/keycodes/keyboard_code_conversion_mac.h" +#import "ui/events/keycodes/keyboard_code_conversion_mac.h" #include <algorithm> diff --git a/chromium/ui/base/keycodes/keyboard_code_conversion_win.cc b/chromium/ui/events/keycodes/keyboard_code_conversion_win.cc index f85cc50b4b5..66eeaa75dc7 100644 --- a/chromium/ui/base/keycodes/keyboard_code_conversion_win.cc +++ b/chromium/ui/events/keycodes/keyboard_code_conversion_win.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/keycodes/keyboard_code_conversion_win.h" +#include "ui/events/keycodes/keyboard_code_conversion_win.h" namespace ui { diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_win.h b/chromium/ui/events/keycodes/keyboard_code_conversion_win.h new file mode 100644 index 00000000000..9d1c5d759fb --- /dev/null +++ b/chromium/ui/events/keycodes/keyboard_code_conversion_win.h @@ -0,0 +1,19 @@ +// Copyright (c) 2011 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. + +#ifndef UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_WIN_H_ +#define UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_WIN_H_ + +#include "ui/events/events_export.h" +#include "ui/events/keycodes/keyboard_codes.h" + +namespace ui { + +// Methods to convert ui::KeyboardCode/Windows virtual key type methods. +EVENTS_EXPORT WORD WindowsKeyCodeForKeyboardCode(KeyboardCode keycode); +EVENTS_EXPORT KeyboardCode KeyboardCodeForWindowsKeyCode(WORD keycode); + +} // namespace ui + +#endif // UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_WIN_H_ diff --git a/chromium/ui/base/keycodes/keyboard_code_conversion_x.cc b/chromium/ui/events/keycodes/keyboard_code_conversion_x.cc index a78354f14e9..8b88e393955 100644 --- a/chromium/ui/base/keycodes/keyboard_code_conversion_x.cc +++ b/chromium/ui/events/keycodes/keyboard_code_conversion_x.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/keycodes/keyboard_code_conversion_x.h" +#include "ui/events/keycodes/keyboard_code_conversion_x.h" #define XK_3270 // for XK_3270_BackTab #include <X11/keysym.h> diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_x.h b/chromium/ui/events/keycodes/keyboard_code_conversion_x.h new file mode 100644 index 00000000000..80b38063fc1 --- /dev/null +++ b/chromium/ui/events/keycodes/keyboard_code_conversion_x.h @@ -0,0 +1,31 @@ +// Copyright (c) 2011 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. + +#ifndef UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_X_H_ +#define UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_X_H_ + +#include "base/basictypes.h" +#include "ui/events/events_export.h" +#include "ui/events/keycodes/keyboard_codes_posix.h" + +typedef union _XEvent XEvent; + +namespace ui { + +EVENTS_EXPORT KeyboardCode KeyboardCodeFromXKeyEvent(XEvent* xev); + +EVENTS_EXPORT KeyboardCode KeyboardCodeFromXKeysym(unsigned int keysym); + +// Returns a character on a standard US PC keyboard from an XEvent. +EVENTS_EXPORT uint16 GetCharacterFromXEvent(XEvent* xev); + +// Converts a KeyboardCode into an X KeySym. +EVENTS_EXPORT int XKeysymForWindowsKeyCode(KeyboardCode keycode, bool shift); + +// Converts an X keycode into an X KeySym. +unsigned int DefaultXKeysymFromHardwareKeycode(unsigned int keycode); + +} // namespace ui + +#endif // UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_X_H_ diff --git a/chromium/ui/base/keycodes/keyboard_codes.h b/chromium/ui/events/keycodes/keyboard_codes.h index 19d6e389c67..00a7847ae9b 100644 --- a/chromium/ui/base/keycodes/keyboard_codes.h +++ b/chromium/ui/events/keycodes/keyboard_codes.h @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_KEYCODES_KEYBOARD_CODES_H_ -#define UI_BASE_KEYCODES_KEYBOARD_CODES_H_ +#ifndef UI_EVENTS_KEYCODES_KEYBOARD_CODES_H_ +#define UI_EVENTS_KEYCODES_KEYBOARD_CODES_H_ #include "build/build_config.h" #if defined(OS_WIN) -#include "ui/base/keycodes/keyboard_codes_win.h" +#include "ui/events/keycodes/keyboard_codes_win.h" #elif defined(OS_POSIX) -#include "ui/base/keycodes/keyboard_codes_posix.h" +#include "ui/events/keycodes/keyboard_codes_posix.h" #endif -#endif // UI_BASE_KEYCODES_KEYBOARD_CODES_H_ +#endif // UI_EVENTS_KEYCODES_KEYBOARD_CODES_H_ diff --git a/chromium/ui/base/keycodes/keyboard_codes_posix.h b/chromium/ui/events/keycodes/keyboard_codes_posix.h index 5879c99897e..1f7e06f96b2 100644 --- a/chromium/ui/base/keycodes/keyboard_codes_posix.h +++ b/chromium/ui/events/keycodes/keyboard_codes_posix.h @@ -28,8 +28,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef UI_BASE_KEYCODES_KEYBOARD_CODES_POSIX_H_ -#define UI_BASE_KEYCODES_KEYBOARD_CODES_POSIX_H_ +#ifndef UI_EVENTS_KEYCODES_KEYBOARD_CODES_POSIX_H_ +#define UI_EVENTS_KEYCODES_KEYBOARD_CODES_POSIX_H_ namespace ui { @@ -225,4 +225,4 @@ enum KeyboardCode { } // namespace ui -#endif // UI_BASE_KEYCODES_KEYBOARD_CODES_POSIX_H_ +#endif // UI_EVENTS_KEYCODES_KEYBOARD_CODES_POSIX_H_ diff --git a/chromium/ui/base/keycodes/keyboard_codes_win.h b/chromium/ui/events/keycodes/keyboard_codes_win.h index fb8ac20f90c..396d38bea7e 100644 --- a/chromium/ui/base/keycodes/keyboard_codes_win.h +++ b/chromium/ui/events/keycodes/keyboard_codes_win.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_KEYCODES_KEYBOARD_CODES_WIN_H_ -#define UI_BASE_KEYCODES_KEYBOARD_CODES_WIN_H_ +#ifndef UI_EVENTS_KEYCODES_KEYBOARD_CODES_WIN_H_ +#define UI_EVENTS_KEYCODES_KEYBOARD_CODES_WIN_H_ #include <windows.h> #include <ime.h> @@ -189,4 +189,4 @@ enum KeyboardCode { } // namespace ui -#endif // UI_BASE_KEYCODES_KEYBOARD_CODES_WIN_H_ +#endif // UI_EVENTS_KEYCODES_KEYBOARD_CODES_WIN_H_ diff --git a/chromium/ui/base/latency_info.cc b/chromium/ui/events/latency_info.cc index 9551450fab5..796f442ae6d 100644 --- a/chromium/ui/base/latency_info.cc +++ b/chromium/ui/events/latency_info.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/latency_info.h" +#include "ui/events/latency_info.h" #include <algorithm> diff --git a/chromium/ui/base/latency_info.h b/chromium/ui/events/latency_info.h index 3482a500a8d..8bf56100dfd 100644 --- a/chromium/ui/base/latency_info.h +++ b/chromium/ui/events/latency_info.h @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_LATENCY_INFO_H_ -#define UI_BASE_LATENCY_INFO_H_ +#ifndef UI_EVENTS_LATENCY_INFO_H_ +#define UI_EVENTS_LATENCY_INFO_H_ #include <map> #include <utility> #include "base/basictypes.h" #include "base/time/time.h" -#include "ui/base/ui_export.h" +#include "ui/events/events_export.h" namespace ui { @@ -35,7 +35,7 @@ enum LatencyComponentType { INPUT_EVENT_LATENCY_ACKED_COMPONENT }; -struct UI_EXPORT LatencyInfo { +struct EVENTS_EXPORT LatencyInfo { struct LatencyComponent { // Nondecreasing number that can be used to determine what events happened // in the component at the time this struct was sent on to the next @@ -93,4 +93,4 @@ struct UI_EXPORT LatencyInfo { } // namespace ui -#endif // UI_BASE_LATENCY_INFO_H_ +#endif // UI_EVENTS_LATENCY_INFO_H_ diff --git a/chromium/ui/base/latency_info_unittest.cc b/chromium/ui/events/latency_info_unittest.cc index bb834787d30..32bb8695765 100644 --- a/chromium/ui/base/latency_info_unittest.cc +++ b/chromium/ui/events/latency_info_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/latency_info.h" +#include "ui/events/latency_info.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chromium/ui/base/ozone/OWNERS b/chromium/ui/events/ozone/OWNERS index 77f21b5cae7..77f21b5cae7 100644 --- a/chromium/ui/base/ozone/OWNERS +++ b/chromium/ui/events/ozone/OWNERS diff --git a/chromium/ui/base/ozone/evdev/key_event_converter_ozone.cc b/chromium/ui/events/ozone/evdev/key_event_converter_ozone.cc index 8766164c8b5..dc949d98366 100644 --- a/chromium/ui/base/ozone/evdev/key_event_converter_ozone.cc +++ b/chromium/ui/events/ozone/evdev/key_event_converter_ozone.cc @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/ozone/evdev/key_event_converter_ozone.h" +#include "ui/events/ozone/evdev/key_event_converter_ozone.h" #include <linux/input.h> -#include "ui/base/events/event.h" -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/keyboard_codes.h" namespace { diff --git a/chromium/ui/base/ozone/evdev/key_event_converter_ozone.h b/chromium/ui/events/ozone/evdev/key_event_converter_ozone.h index 2ce3c22322b..2fdcb638a86 100644 --- a/chromium/ui/base/ozone/evdev/key_event_converter_ozone.h +++ b/chromium/ui/events/ozone/evdev/key_event_converter_ozone.h @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_OZONE_EVDEV_KEY_EVENT_CONVERTER_OZONE_H_ -#define UI_BASE_OZONE_EVDEV_KEY_EVENT_CONVERTER_OZONE_H_ +#ifndef UI_EVENTS_OZONE_EVDEV_KEY_EVENT_CONVERTER_OZONE_H_ +#define UI_EVENTS_OZONE_EVDEV_KEY_EVENT_CONVERTER_OZONE_H_ -#include "ui/base/ozone/event_converter_ozone.h" +#include "ui/events/ozone/event_converter_ozone.h" namespace ui { @@ -24,4 +24,5 @@ class KeyEventConverterOzone : public EventConverterOzone { } // namspace ui -#endif // UI_BASE_OZONE_EVDEV_KEY_EVENT_CONVERTER_OZONE_H_ +#endif // UI_EVENTS_OZONE_EVDEV_KEY_EVENT_CONVERTER_OZONE_H_ + diff --git a/chromium/ui/base/ozone/evdev/touch_event_converter_ozone.cc b/chromium/ui/events/ozone/evdev/touch_event_converter_ozone.cc index 0e4f560305e..30e94139084 100644 --- a/chromium/ui/base/ozone/evdev/touch_event_converter_ozone.cc +++ b/chromium/ui/events/ozone/evdev/touch_event_converter_ozone.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/ozone/evdev/touch_event_converter_ozone.h" +#include "ui/events/ozone/evdev/touch_event_converter_ozone.h" #include <fcntl.h> #include <linux/input.h> @@ -11,15 +11,16 @@ #include <unistd.h> #include <cmath> +#include <limits> #include "base/bind.h" #include "base/callback.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" #include "base/message_loop/message_pump_ozone.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/ozone/surface_factory_ozone.h" +#include "ui/events/event.h" +#include "ui/events/event_constants.h" +#include "ui/gfx/ozone/surface_factory_ozone.h" namespace { @@ -36,6 +37,8 @@ TouchEventConverterOzone::TouchEventConverterOzone(int fd, int id) pressure_max_(0), x_scale_(1.), y_scale_(1.), + x_max_(std::numeric_limits<int>::max()), + y_max_(std::numeric_limits<int>::max()), current_slot_(0), fd_(fd), id_(id) { @@ -75,14 +78,16 @@ void TouchEventConverterOzone::Init() { } else { LOG(WARNING) << "failed ioctl EVIOCGABS ABS_Y event" << id_; } - if (x_max && y_max && SurfaceFactoryOzone::GetInstance()) { + if (x_max && y_max && gfx::SurfaceFactoryOzone::GetInstance()) { const char* display = - SurfaceFactoryOzone::GetInstance()->DefaultDisplaySpec(); + gfx::SurfaceFactoryOzone::GetInstance()->DefaultDisplaySpec(); int screen_width, screen_height; int sc = sscanf(display, "%dx%d", &screen_width, &screen_height); if (sc == 2) { x_scale_ = (double)screen_width / (x_max - x_min); y_scale_ = (double)screen_height / (y_max - y_min); + x_max_ = screen_width - 1; + y_max_ = screen_height - 1; LOG(INFO) << "touch input x_scale=" << x_scale_ << " y_scale=" << y_scale_; } else { @@ -151,7 +156,8 @@ void TouchEventConverterOzone::OnFileCanReadWithoutBlocking(int fd) { // TODO(rjkroege): Support elliptical finger regions. scoped_ptr<TouchEvent> tev(new TouchEvent( events_[j].type_, - gfx::Point(events_[j].x_, events_[j].y_), + gfx::Point(std::min(x_max_, events_[j].x_), + std::min(y_max_, events_[j].y_)), /* flags */ 0, /* touch_id */ j, base::TimeDelta::FromMicroseconds( @@ -160,8 +166,11 @@ void TouchEventConverterOzone::OnFileCanReadWithoutBlocking(int fd) { events_[j].pressure_ * kFingerWidth, /* angle */ 0., events_[j].pressure_)); - events_[j].type_ = ET_TOUCH_MOVED; DispatchEvent(tev.PassAs<ui::Event>()); + + // Subsequent events for this finger will be touch-move until it + // is released. + events_[j].type_ = ET_TOUCH_MOVED; } } altered_slots_.reset(); diff --git a/chromium/ui/base/ozone/evdev/touch_event_converter_ozone.h b/chromium/ui/events/ozone/evdev/touch_event_converter_ozone.h index ef96be405b0..730bfaffc19 100644 --- a/chromium/ui/base/ozone/evdev/touch_event_converter_ozone.h +++ b/chromium/ui/events/ozone/evdev/touch_event_converter_ozone.h @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_OZONE_EVDEV_TOUCH_EVENT_CONVERTER_OZONE_H_ -#define UI_BASE_OZONE_EVDEV_TOUCH_EVENT_CONVERTER_OZONE_H_ +#ifndef UI_EVENTS_OZONE_EVDEV_TOUCH_EVENT_CONVERTER_OZONE_H_ +#define UI_EVENTS_OZONE_EVDEV_TOUCH_EVENT_CONVERTER_OZONE_H_ #include <bitset> #include "base/compiler_specific.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/ozone/event_converter_ozone.h" -#include "ui/base/ui_export.h" +#include "ui/events/event_constants.h" +#include "ui/events/events_export.h" +#include "ui/events/ozone/event_converter_ozone.h" namespace ui { @@ -42,6 +42,10 @@ class UI_EXPORT TouchEventConverterOzone : public EventConverterOzone { float x_scale_; float y_scale_; + // Maximum coordinate-values allowed for the events. + int x_max_; + int y_max_; + // Touch point currently being updated from the /dev/input/event* stream. int current_slot_; @@ -74,4 +78,5 @@ class UI_EXPORT TouchEventConverterOzone : public EventConverterOzone { } // namespace ui -#endif // UI_BASE_OZONE_EVDEV_TOUCH_EVENT_CONVERTER_OZONE_H_ +#endif // UI_EVENTS_OZONE_EVDEV_TOUCH_EVENT_CONVERTER_OZONE_H_ + diff --git a/chromium/ui/base/ozone/evdev/touch_event_converter_ozone_unittest.cc b/chromium/ui/events/ozone/evdev/touch_event_converter_ozone_unittest.cc index 61bf54bda5b..709b5c129d3 100644 --- a/chromium/ui/base/ozone/evdev/touch_event_converter_ozone_unittest.cc +++ b/chromium/ui/events/ozone/evdev/touch_event_converter_ozone_unittest.cc @@ -16,8 +16,8 @@ #include "base/run_loop.h" #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/events/event.h" -#include "ui/base/ozone/evdev/touch_event_converter_ozone.h" +#include "ui/events/event.h" +#include "ui/events/ozone/evdev/touch_event_converter_ozone.h" namespace { diff --git a/chromium/ui/base/ozone/event_converter_ozone.cc b/chromium/ui/events/ozone/event_converter_ozone.cc index 485ea22bc0e..2bb6164e80b 100644 --- a/chromium/ui/base/ozone/event_converter_ozone.cc +++ b/chromium/ui/events/ozone/event_converter_ozone.cc @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/ozone/event_converter_ozone.h" +#include "ui/events/ozone/event_converter_ozone.h" #include "base/bind.h" #include "base/message_loop/message_loop.h" #include "base/message_loop/message_pump_ozone.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" namespace { diff --git a/chromium/ui/base/ozone/event_converter_ozone.h b/chromium/ui/events/ozone/event_converter_ozone.h index 58db8363bc5..b28df34fb6b 100644 --- a/chromium/ui/base/ozone/event_converter_ozone.h +++ b/chromium/ui/events/ozone/event_converter_ozone.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_OZONE_EVENT_CONVERTER_OZONE_H_ -#define UI_BASE_OZONE_EVENT_CONVERTER_OZONE_H_ +#ifndef UI_EVENTS_OZONE_EVENT_CONVERTER_OZONE_H_ +#define UI_EVENTS_OZONE_EVENT_CONVERTER_OZONE_H_ #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_pump_libevent.h" @@ -35,4 +35,4 @@ class EventConverterOzone : public base::MessagePumpLibevent::Watcher { } // namespace ui -#endif // UI_BASE_OZONE_EVENT_CONVERTER_OZONE_H_ +#endif // UI_EVENTS_OZONE_EVENT_CONVERTER_OZONE_H_ diff --git a/chromium/ui/base/ozone/event_factory_delegate_ozone.h b/chromium/ui/events/ozone/event_factory_delegate_ozone.h index 04d427dd8fc..e16adc81985 100644 --- a/chromium/ui/base/ozone/event_factory_delegate_ozone.h +++ b/chromium/ui/events/ozone/event_factory_delegate_ozone.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_OZONE_EVENT_FACTORY_DELEGATE_OZONE_H_ -#define UI_BASE_OZONE_EVENT_FACTORY_DELEGATE_OZONE_H_ +#ifndef UI_EVENTS_OZONE_EVENT_FACTORY_DELEGATE_OZONE_H_ +#define UI_EVENTS_OZONE_EVENT_FACTORY_DELEGATE_OZONE_H_ namespace ui { class Event; @@ -26,4 +26,4 @@ class UI_EXPORT EventFactoryDelegateOzone { } // namespace ui -#endif // UI_BASE_OZONE_EVENT_FACTORY_DELEGATE_OZONE_H_ +#endif // UI_EVENTS_OZONE_EVENT_FACTORY_DELEGATE_OZONE_H_ diff --git a/chromium/ui/base/ozone/event_factory_ozone.cc b/chromium/ui/events/ozone/event_factory_ozone.cc index afeff2b7a19..acdf9958b55 100644 --- a/chromium/ui/base/ozone/event_factory_ozone.cc +++ b/chromium/ui/events/ozone/event_factory_ozone.cc @@ -2,8 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/ozone/event_factory_ozone.h" +#include "ui/events/ozone/event_factory_ozone.h" +#include <errno.h> #include <fcntl.h> #include <linux/input.h> #include <poll.h> @@ -12,9 +13,9 @@ #include "base/message_loop/message_pump_ozone.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" -#include "ui/base/ozone/evdev/key_event_converter_ozone.h" -#include "ui/base/ozone/evdev/touch_event_converter_ozone.h" -#include "ui/base/ozone/event_factory_delegate_ozone.h" +#include "ui/events/ozone/evdev/key_event_converter_ozone.h" +#include "ui/events/ozone/evdev/touch_event_converter_ozone.h" +#include "ui/events/ozone/event_factory_delegate_ozone.h" namespace ui { @@ -45,8 +46,10 @@ void EventFactoryOzone::CreateStartupEventConverters() { for (int id = 0; true; id++) { std::string path = base::StringPrintf("/dev/input/event%d", id); int fd = open(path.c_str(), O_RDONLY | O_NONBLOCK); - if (fd < 0) + if (fd < 0) { + DLOG(ERROR) << "Cannot open '" << path << "': " << strerror(errno); break; + } size_t evtype = 0; COMPILE_ASSERT(sizeof(evtype) * 8 >= EV_MAX, evtype_wide_enough); if (ioctl(fd, EVIOCGBIT(0, sizeof(evtype)), &evtype) == -1) { diff --git a/chromium/ui/base/ozone/event_factory_ozone.h b/chromium/ui/events/ozone/event_factory_ozone.h index b88654e5264..489d4aebce1 100644 --- a/chromium/ui/base/ozone/event_factory_ozone.h +++ b/chromium/ui/events/ozone/event_factory_ozone.h @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_OZONE_EVENT_FACTORY_OZONE_H_ -#define UI_BASE_OZONE_EVENT_FACTORY_OZONE_H_ +#ifndef UI_EVENTS_OZONE_EVENT_FACTORY_OZONE_H_ +#define UI_EVENTS_OZONE_EVENT_FACTORY_OZONE_H_ #include <map> #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_pump_libevent.h" -#include "ui/base/ozone/event_converter_ozone.h" -#include "ui/base/ui_export.h" +#include "ui/events/events_export.h" +#include "ui/events/ozone/event_converter_ozone.h" namespace ui { @@ -57,4 +57,4 @@ class UI_EXPORT EventFactoryOzone { } // namespace ui -#endif // UI_BASE_OZONE_EVENT_FACTORY_OZONE_H_ +#endif // UI_EVENTS_OZONE_EVENT_FACTORY_OZONE_H_ diff --git a/chromium/ui/base/ozone/events_ozone.cc b/chromium/ui/events/ozone/events_ozone.cc index cad17f69728..0db40f48a2c 100644 --- a/chromium/ui/base/ozone/events_ozone.cc +++ b/chromium/ui/events/ozone/events_ozone.cc @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/events/event.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/events/event_utils.h" +#include "ui/events/event.h" +#include "ui/events/event_constants.h" +#include "ui/events/event_utils.h" namespace ui { diff --git a/chromium/ui/gfx/android/device_display_info.h b/chromium/ui/gfx/android/device_display_info.h index af7bb622b25..9f90f897b6a 100644 --- a/chromium/ui/gfx/android/device_display_info.h +++ b/chromium/ui/gfx/android/device_display_info.h @@ -10,7 +10,7 @@ #include "base/android/scoped_java_ref.h" #include "base/basictypes.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" namespace gfx { diff --git a/chromium/ui/gfx/android/java_bitmap.cc b/chromium/ui/gfx/android/java_bitmap.cc index e292b385aa1..6c2eaa845a2 100644 --- a/chromium/ui/gfx/android/java_bitmap.cc +++ b/chromium/ui/gfx/android/java_bitmap.cc @@ -6,6 +6,7 @@ #include <android/bitmap.h> +#include "base/android/jni_string.h" #include "base/logging.h" #include "jni/BitmapHelper_jni.h" #include "skia/ext/image_operations.h" @@ -61,32 +62,20 @@ ScopedJavaLocalRef<jobject> ConvertToJavaBitmap(const SkBitmap* skbitmap) { return jbitmap; } -static ScopedJavaLocalRef<jobject> CreateJavaBitmapFromResource( - const char* name, gfx::Size requested_size) { - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jstring> jname(env, env->NewStringUTF(name)); - return ui::Java_BitmapHelper_decodeDrawableResource(env, - jname.obj(), - requested_size.width(), - requested_size.height()); -} - -static SkBitmap ConvertToSkBitmap(ScopedJavaLocalRef<jobject> jbitmap) { - if (jbitmap.is_null()) - return SkBitmap(); +SkBitmap CreateSkBitmapFromJavaBitmap(JavaBitmap& jbitmap) { + DCHECK_EQ(jbitmap.format(), ANDROID_BITMAP_FORMAT_RGBA_8888); - JavaBitmap src_lock(jbitmap.obj()); - DCHECK_EQ(src_lock.format(), ANDROID_BITMAP_FORMAT_RGBA_8888); - - gfx::Size src_size = src_lock.size(); + gfx::Size src_size = jbitmap.size(); SkBitmap skbitmap; skbitmap.setConfig(SkBitmap::kARGB_8888_Config, - src_size.width(), src_size.height(), src_lock.stride()); + src_size.width(), + src_size.height(), + jbitmap.stride()); skbitmap.allocPixels(); SkAutoLockPixels dst_lock(skbitmap); - void* src_pixels = src_lock.pixels(); + void* src_pixels = jbitmap.pixels(); void* dst_pixels = skbitmap.getPixels(); memcpy(dst_pixels, src_pixels, skbitmap.getSize()); @@ -96,13 +85,17 @@ static SkBitmap ConvertToSkBitmap(ScopedJavaLocalRef<jobject> jbitmap) { SkBitmap CreateSkBitmapFromResource(const char* name, gfx::Size size) { DCHECK(!size.IsEmpty()); - SkBitmap bitmap = - ConvertToSkBitmap(CreateJavaBitmapFromResource(name, size)); - if (bitmap.isNull()) - return bitmap; - return skia::ImageOperations::Resize(bitmap, - skia::ImageOperations::RESIZE_GOOD, - size.width(), size.height()); + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jstring> jname(env, env->NewStringUTF(name)); + ScopedJavaLocalRef<jobject> jobj(ui::Java_BitmapHelper_decodeDrawableResource( + env, jname.obj(), size.width(), size.height())); + if (jobj.is_null()) + return SkBitmap(); + + JavaBitmap jbitmap(jobj.obj()); + SkBitmap bitmap = CreateSkBitmapFromJavaBitmap(jbitmap); + return skia::ImageOperations::Resize( + bitmap, skia::ImageOperations::RESIZE_BOX, size.width(), size.height()); } } // namespace gfx diff --git a/chromium/ui/gfx/android/java_bitmap.h b/chromium/ui/gfx/android/java_bitmap.h index 9dd49fb8a38..319ad79eb1e 100644 --- a/chromium/ui/gfx/android/java_bitmap.h +++ b/chromium/ui/gfx/android/java_bitmap.h @@ -44,7 +44,10 @@ class UI_EXPORT JavaBitmap { UI_EXPORT base::android::ScopedJavaLocalRef<jobject> ConvertToJavaBitmap( const SkBitmap* skbitmap); +UI_EXPORT SkBitmap CreateSkBitmapFromJavaBitmap(JavaBitmap& jbitmap); + // If the resource loads successfully, it will be resized to |size|. +// Note: If the source resource is smaller than |size|, quality may suffer. UI_EXPORT SkBitmap CreateSkBitmapFromResource(const char* name, gfx::Size size); } // namespace gfx diff --git a/chromium/ui/base/animation/animation.cc b/chromium/ui/gfx/animation/animation.cc index 78ee4d9c213..ba0bac822cc 100644 --- a/chromium/ui/base/animation/animation.cc +++ b/chromium/ui/gfx/animation/animation.cc @@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/animation/animation.h" +#include "ui/gfx/animation/animation.h" -#include "ui/base/animation/animation_container.h" -#include "ui/base/animation/animation_delegate.h" -#include "ui/base/animation/tween.h" +#include "ui/gfx/animation/animation_container.h" +#include "ui/gfx/animation/animation_delegate.h" +#include "ui/gfx/animation/tween.h" #include "ui/gfx/rect.h" #if defined(OS_WIN) #include "base/win/windows_version.h" #endif -namespace ui { +namespace gfx { Animation::Animation(base::TimeDelta timer_interval) : timer_interval_(timer_interval), @@ -121,4 +121,4 @@ base::TimeDelta Animation::GetTimerInterval() const { return timer_interval_; } -} // namespace ui +} // namespace gfx diff --git a/chromium/ui/base/animation/animation.h b/chromium/ui/gfx/animation/animation.h index 361ab15dbbd..32d297e2939 100644 --- a/chromium/ui/base/animation/animation.h +++ b/chromium/ui/gfx/animation/animation.h @@ -2,19 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_ANIMATION_ANIMATION_H_ -#define UI_BASE_ANIMATION_ANIMATION_H_ +#ifndef UI_GFX_ANIMATION_ANIMATION_H_ +#define UI_GFX_ANIMATION_ANIMATION_H_ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" -#include "ui/base/animation/animation_container_element.h" +#include "ui/gfx/animation/animation_container_element.h" namespace gfx { class Rect; } -namespace ui { +namespace gfx { class AnimationContainer; class AnimationDelegate; @@ -25,7 +25,7 @@ class AnimationDelegate; // // To subclass override Step, which is invoked as the animation progresses and // GetCurrentValue() to return the value appropriate to the animation. -class UI_EXPORT Animation : public AnimationContainerElement { +class GFX_EXPORT Animation : public AnimationContainerElement { public: explicit Animation(base::TimeDelta timer_interval); virtual ~Animation(); @@ -104,6 +104,6 @@ class UI_EXPORT Animation : public AnimationContainerElement { DISALLOW_COPY_AND_ASSIGN(Animation); }; -} // namespace ui +} // namespace gfx -#endif // UI_BASE_ANIMATION_ANIMATION_H_ +#endif // UI_GFX_ANIMATION_ANIMATION_H_ diff --git a/chromium/ui/base/animation/animation_container.cc b/chromium/ui/gfx/animation/animation_container.cc index c82d26b9aa5..c76f1bb7797 100644 --- a/chromium/ui/base/animation/animation_container.cc +++ b/chromium/ui/gfx/animation/animation_container.cc @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/animation/animation_container.h" +#include "ui/gfx/animation/animation_container.h" -#include "ui/base/animation/animation_container_element.h" -#include "ui/base/animation/animation_container_observer.h" +#include "ui/gfx/animation/animation_container_element.h" +#include "ui/gfx/animation/animation_container_observer.h" using base::TimeDelta; using base::TimeTicks; -namespace ui { +namespace gfx { AnimationContainer::AnimationContainer() : last_tick_time_(TimeTicks::Now()), @@ -101,4 +101,4 @@ TimeDelta AnimationContainer::GetMinInterval() { return min; } -} // namespace ui +} // namespace gfx diff --git a/chromium/ui/base/animation/animation_container.h b/chromium/ui/gfx/animation/animation_container.h index e1631f082e4..bb59f8f0cc7 100644 --- a/chromium/ui/base/animation/animation_container.h +++ b/chromium/ui/gfx/animation/animation_container.h @@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_ANIMATION_ANIMATION_CONTAINER_H_ -#define UI_BASE_ANIMATION_ANIMATION_CONTAINER_H_ +#ifndef UI_GFX_ANIMATION_ANIMATION_CONTAINER_H_ +#define UI_GFX_ANIMATION_ANIMATION_CONTAINER_H_ #include <set> #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "base/timer/timer.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" -namespace ui { +namespace gfx { class AnimationContainerElement; class AnimationContainerObserver; @@ -25,7 +25,7 @@ class AnimationContainerObserver; // // AnimationContainer is ref counted. Each Animation contained within the // AnimationContainer own it. -class UI_EXPORT AnimationContainer +class GFX_EXPORT AnimationContainer : public base::RefCounted<AnimationContainer> { public: AnimationContainer(); @@ -86,6 +86,6 @@ class UI_EXPORT AnimationContainer DISALLOW_COPY_AND_ASSIGN(AnimationContainer); }; -} // namespace ui +} // namespace gfx -#endif // UI_BASE_ANIMATION_ANIMATION_CONTAINER_H_ +#endif // UI_GFX_ANIMATION_ANIMATION_CONTAINER_H_ diff --git a/chromium/ui/base/animation/animation_container_element.h b/chromium/ui/gfx/animation/animation_container_element.h index 1afa2b8b0c2..224655eb318 100644 --- a/chromium/ui/base/animation/animation_container_element.h +++ b/chromium/ui/gfx/animation/animation_container_element.h @@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_ANIMATION_ANIMATION_CONTAINER_ELEMENT_H_ -#define UI_BASE_ANIMATION_ANIMATION_CONTAINER_ELEMENT_H_ +#ifndef UI_GFX_ANIMATION_ANIMATION_CONTAINER_ELEMENT_H_ +#define UI_GFX_ANIMATION_ANIMATION_CONTAINER_ELEMENT_H_ #include "base/time/time.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" -namespace ui { +namespace gfx { // Interface for the elements the AnimationContainer contains. This is // implemented by Animation. -class UI_EXPORT AnimationContainerElement { +class GFX_EXPORT AnimationContainerElement { public: // Sets the start of the animation. This is invoked from // AnimationContainer::Start. @@ -29,6 +29,6 @@ class UI_EXPORT AnimationContainerElement { virtual ~AnimationContainerElement() {} }; -} // namespace ui +} // namespace gfx -#endif // UI_BASE_ANIMATION_ANIMATION_CONTAINER_ELEMENT_H_ +#endif // UI_GFX_ANIMATION_ANIMATION_CONTAINER_ELEMENT_H_ diff --git a/chromium/ui/base/animation/animation_container_observer.h b/chromium/ui/gfx/animation/animation_container_observer.h index 06948ef3449..a5051679626 100644 --- a/chromium/ui/base/animation/animation_container_observer.h +++ b/chromium/ui/gfx/animation/animation_container_observer.h @@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_ANIMATION_ANIMATION_CONTAINER_OBSERVER_H_ -#define UI_BASE_ANIMATION_ANIMATION_CONTAINER_OBSERVER_H_ +#ifndef UI_GFX_ANIMATION_ANIMATION_CONTAINER_OBSERVER_H_ +#define UI_GFX_ANIMATION_ANIMATION_CONTAINER_OBSERVER_H_ -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" -namespace ui { +namespace gfx { class AnimationContainer; // The observer is notified after every update of the animations managed by // the container. -class UI_EXPORT AnimationContainerObserver { +class GFX_EXPORT AnimationContainerObserver { public: // Invoked on every tick of the timer managed by the container and after // all the animations have updated. @@ -27,6 +27,6 @@ class UI_EXPORT AnimationContainerObserver { virtual ~AnimationContainerObserver() {} }; -} // namespace ui +} // namespace gfx -#endif // UI_BASE_ANIMATION_ANIMATION_CONTAINER_OBSERVER_H_ +#endif // UI_GFX_ANIMATION_ANIMATION_CONTAINER_OBSERVER_H_ diff --git a/chromium/ui/base/animation/animation_container_unittest.cc b/chromium/ui/gfx/animation/animation_container_unittest.cc index c516cf325f8..25977c26161 100644 --- a/chromium/ui/base/animation/animation_container_unittest.cc +++ b/chromium/ui/gfx/animation/animation_container_unittest.cc @@ -2,17 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "ui/gfx/animation/animation_container.h" + #include "base/memory/scoped_ptr.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/animation/animation_container.h" -#include "ui/base/animation/animation_container_observer.h" -#include "ui/base/animation/linear_animation.h" -#include "ui/base/animation/test_animation_delegate.h" +#include "ui/gfx/animation/animation_container_observer.h" +#include "ui/gfx/animation/linear_animation.h" +#include "ui/gfx/animation/test_animation_delegate.h" using testing::AtLeast; -namespace ui { +namespace gfx { namespace { @@ -123,4 +124,4 @@ TEST_F(AnimationContainerTest, Observer) { container->set_observer(NULL); } -} // namespace ui +} // namespace gfx diff --git a/chromium/ui/base/animation/animation_delegate.h b/chromium/ui/gfx/animation/animation_delegate.h index 9a7edbcd1af..94303ddd93a 100644 --- a/chromium/ui/base/animation/animation_delegate.h +++ b/chromium/ui/gfx/animation/animation_delegate.h @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_ANIMATION_ANIMATION_DELEGATE_H_ -#define UI_BASE_ANIMATION_ANIMATION_DELEGATE_H_ +#ifndef UI_GFX_ANIMATION_ANIMATION_DELEGATE_H_ +#define UI_GFX_ANIMATION_ANIMATION_DELEGATE_H_ -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" -namespace ui { +namespace gfx { class Animation; @@ -15,7 +15,7 @@ class Animation; // // Implement this interface when you want to receive notifications about the // state of an animation. -class UI_EXPORT AnimationDelegate { +class GFX_EXPORT AnimationDelegate { public: // Called when an animation has completed. virtual void AnimationEnded(const Animation* animation) {} @@ -30,6 +30,6 @@ class UI_EXPORT AnimationDelegate { virtual ~AnimationDelegate() {} }; -} // namespace ui +} // namespace gfx -#endif // UI_BASE_ANIMATION_ANIMATION_DELEGATE_H_ +#endif // UI_GFX_ANIMATION_ANIMATION_DELEGATE_H_ diff --git a/chromium/ui/base/animation/animation_unittest.cc b/chromium/ui/gfx/animation/animation_unittest.cc index 007f92d07d4..00f1e2626c1 100644 --- a/chromium/ui/base/animation/animation_unittest.cc +++ b/chromium/ui/gfx/animation/animation_unittest.cc @@ -3,15 +3,15 @@ // found in the LICENSE file. #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/animation/animation_delegate.h" -#include "ui/base/animation/linear_animation.h" -#include "ui/base/animation/test_animation_delegate.h" +#include "ui/gfx/animation/animation_delegate.h" +#include "ui/gfx/animation/linear_animation.h" +#include "ui/gfx/animation/test_animation_delegate.h" #if defined(OS_WIN) #include "base/win/windows_version.h" #endif -namespace ui { +namespace gfx { class AnimationTest: public testing::Test { private: @@ -155,4 +155,4 @@ TEST_F(AnimationTest, StartState) { EXPECT_EQ(0.0, animation.GetCurrentValue()); } -} // namespace ui +} // namespace gfx diff --git a/chromium/ui/base/animation/linear_animation.cc b/chromium/ui/gfx/animation/linear_animation.cc index 33bd1d1a481..b3f3df0e0c9 100644 --- a/chromium/ui/base/animation/linear_animation.cc +++ b/chromium/ui/gfx/animation/linear_animation.cc @@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/animation/linear_animation.h" +#include "ui/gfx/animation/linear_animation.h" #include <math.h> -#include "ui/base/animation/animation_container.h" -#include "ui/base/animation/animation_delegate.h" +#include "ui/gfx/animation/animation_container.h" +#include "ui/gfx/animation/animation_delegate.h" using base::Time; using base::TimeDelta; -namespace ui { +namespace gfx { static TimeDelta CalculateInterval(int frame_rate) { int timer_interval = 1000000 / frame_rate; @@ -105,4 +105,4 @@ bool LinearAnimation::ShouldSendCanceledFromStop() { return state_ != 1; } -} // namespace ui +} // namespace gfx diff --git a/chromium/ui/base/animation/linear_animation.h b/chromium/ui/gfx/animation/linear_animation.h index 307a9fbe111..401f1be18bb 100644 --- a/chromium/ui/base/animation/linear_animation.h +++ b/chromium/ui/gfx/animation/linear_animation.h @@ -2,19 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_ANIMATION_LINEAR_ANIMATION_H_ -#define UI_BASE_ANIMATION_LINEAR_ANIMATION_H_ +#ifndef UI_GFX_ANIMATION_LINEAR_ANIMATION_H_ +#define UI_GFX_ANIMATION_LINEAR_ANIMATION_H_ #include "base/time/time.h" -#include "ui/base/animation/animation.h" +#include "ui/gfx/animation/animation.h" -namespace ui { +namespace gfx { class AnimationDelegate; // Linear time bounded animation. As the animation progresses AnimateToState is // invoked. -class UI_EXPORT LinearAnimation : public Animation { +class GFX_EXPORT LinearAnimation : public Animation { public: // Initializes everything except the duration. // @@ -74,6 +74,6 @@ class UI_EXPORT LinearAnimation : public Animation { DISALLOW_COPY_AND_ASSIGN(LinearAnimation); }; -} // namespace ui +} // namespace gfx #endif // APP_LINEAR_ANIMATION_H_ diff --git a/chromium/ui/base/animation/multi_animation.cc b/chromium/ui/gfx/animation/multi_animation.cc index 2e9e4772db6..4ecc73c805a 100644 --- a/chromium/ui/base/animation/multi_animation.cc +++ b/chromium/ui/gfx/animation/multi_animation.cc @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/animation/multi_animation.h" +#include "ui/gfx/animation/multi_animation.h" #include "base/logging.h" -#include "ui/base/animation/animation_delegate.h" +#include "ui/gfx/animation/animation_delegate.h" -namespace ui { +namespace gfx { // Default interval, in ms. static const int kDefaultTimerInterval = 20; @@ -91,4 +91,4 @@ const MultiAnimation::Part& MultiAnimation::GetPart(int* time_ms, return parts_[0]; } -} // namespace ui +} // namespace gfx diff --git a/chromium/ui/base/animation/multi_animation.h b/chromium/ui/gfx/animation/multi_animation.h index cbe36c4c752..f0480980576 100644 --- a/chromium/ui/base/animation/multi_animation.h +++ b/chromium/ui/gfx/animation/multi_animation.h @@ -2,21 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_ANIMATION_MULTI_ANIMATION_H_ -#define UI_BASE_ANIMATION_MULTI_ANIMATION_H_ +#ifndef UI_GFX_ANIMATION_MULTI_ANIMATION_H_ +#define UI_GFX_ANIMATION_MULTI_ANIMATION_H_ #include <vector> -#include "ui/base/animation/animation.h" -#include "ui/base/animation/tween.h" +#include "ui/gfx/animation/animation.h" +#include "ui/gfx/animation/tween.h" -namespace ui { +namespace gfx { // MultiAnimation is an animation that consists of a number of sub animations. // To create a MultiAnimation pass in the parts, invoke Start() and the delegate // is notified as the animation progresses. By default MultiAnimation runs until // Stop is invoked, see |set_continuous()| for details. -class UI_EXPORT MultiAnimation : public Animation { +class GFX_EXPORT MultiAnimation : public Animation { public: // Defines part of the animation. Each part consists of the following: // @@ -91,6 +91,6 @@ class UI_EXPORT MultiAnimation : public Animation { DISALLOW_COPY_AND_ASSIGN(MultiAnimation); }; -} // namespace ui +} // namespace gfx -#endif // UI_BASE_ANIMATION_MULTI_ANIMATION_H_ +#endif // UI_GFX_ANIMATION_MULTI_ANIMATION_H_ diff --git a/chromium/ui/base/animation/multi_animation_unittest.cc b/chromium/ui/gfx/animation/multi_animation_unittest.cc index 0c21939c7f0..b8a11fdacf2 100644 --- a/chromium/ui/base/animation/multi_animation_unittest.cc +++ b/chromium/ui/gfx/animation/multi_animation_unittest.cc @@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "ui/gfx/animation/multi_animation.h" + #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/animation/animation_container_element.h" -#include "ui/base/animation/multi_animation.h" +#include "ui/gfx/animation/animation_container_element.h" -namespace ui { +namespace gfx { TEST(MultiAnimationTest, Basic) { // Create a MultiAnimation with two parts. @@ -88,4 +89,4 @@ TEST(MultiAnimationTest, Cycle) { EXPECT_EQ(.5, animation.GetCurrentValue()); } -} // namespace ui +} // namespace gfx diff --git a/chromium/ui/base/animation/slide_animation.cc b/chromium/ui/gfx/animation/slide_animation.cc index e73474cbaaa..d08ac41d9af 100644 --- a/chromium/ui/base/animation/slide_animation.cc +++ b/chromium/ui/gfx/animation/slide_animation.cc @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/animation/slide_animation.h" +#include "ui/gfx/animation/slide_animation.h" #include <math.h> -namespace ui { +namespace gfx { // How many frames per second to target. static const int kDefaultFrameRateHz = 60; @@ -111,4 +111,4 @@ void SlideAnimation::AnimateToState(double state) { } } -} // namespace ui +} // namespace gfx diff --git a/chromium/ui/base/animation/slide_animation.h b/chromium/ui/gfx/animation/slide_animation.h index 709633b7642..8fdf8f86970 100644 --- a/chromium/ui/base/animation/slide_animation.h +++ b/chromium/ui/gfx/animation/slide_animation.h @@ -2,19 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_ANIMATION_SLIDE_ANIMATION_H_ -#define UI_BASE_ANIMATION_SLIDE_ANIMATION_H_ +#ifndef UI_GFX_ANIMATION_SLIDE_ANIMATION_H_ +#define UI_GFX_ANIMATION_SLIDE_ANIMATION_H_ -#include "ui/base/animation/linear_animation.h" -#include "ui/base/animation/tween.h" +#include "ui/gfx/animation/linear_animation.h" +#include "ui/gfx/animation/tween.h" -namespace ui { +namespace gfx { // Slide Animation // // Used for reversible animations and as a general helper class. Typical usage: // -// #include "ui/base/animation/slide_animation.h" +// #include "ui/gfx/animation/slide_animation.h" // // class MyClass : public AnimationDelegate { // public: @@ -44,7 +44,7 @@ namespace ui { // private: // scoped_ptr<SlideAnimation> animation_; // } -class UI_EXPORT SlideAnimation : public LinearAnimation { +class GFX_EXPORT SlideAnimation : public LinearAnimation { public: explicit SlideAnimation(AnimationDelegate* target); virtual ~SlideAnimation(); @@ -96,6 +96,6 @@ class UI_EXPORT SlideAnimation : public LinearAnimation { DISALLOW_COPY_AND_ASSIGN(SlideAnimation); }; -} // namespace ui +} // namespace gfx -#endif // UI_BASE_ANIMATION_SLIDE_ANIMATION_H_ +#endif // UI_GFX_ANIMATION_SLIDE_ANIMATION_H_ diff --git a/chromium/ui/base/animation/slide_animation_unittest.cc b/chromium/ui/gfx/animation/slide_animation_unittest.cc index afd32b750aa..9d4f5343db1 100644 --- a/chromium/ui/base/animation/slide_animation_unittest.cc +++ b/chromium/ui/gfx/animation/slide_animation_unittest.cc @@ -2,13 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "ui/gfx/animation/slide_animation.h" + #include "base/memory/scoped_ptr.h" #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/animation/slide_animation.h" -#include "ui/base/animation/test_animation_delegate.h" +#include "ui/gfx/animation/test_animation_delegate.h" -namespace ui { +namespace gfx { // Class to provide access to SlideAnimation internals for testing. class SlideAnimation::TestApi { @@ -101,4 +102,4 @@ TEST_F(SlideAnimationTest, DontNotifyOnDelete) { EXPECT_FALSE(delegate.canceled()); } -} // namespace ui +} // namespace gfx diff --git a/chromium/ui/base/animation/test_animation_delegate.h b/chromium/ui/gfx/animation/test_animation_delegate.h index 3cdaf8c414f..5bf6ea0a43b 100644 --- a/chromium/ui/base/animation/test_animation_delegate.h +++ b/chromium/ui/gfx/animation/test_animation_delegate.h @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_ANIMATION_TEST_ANIMATION_DELEGATE_H_ -#define UI_BASE_ANIMATION_TEST_ANIMATION_DELEGATE_H_ +#ifndef UI_GFX_ANIMATION_TEST_ANIMATION_DELEGATE_H_ +#define UI_GFX_ANIMATION_TEST_ANIMATION_DELEGATE_H_ #include "base/message_loop/message_loop.h" -#include "ui/base/animation/animation_delegate.h" +#include "ui/gfx/animation/animation_delegate.h" -namespace ui { +namespace gfx { // Trivial AnimationDelegate implementation. AnimationEnded/Canceled quit the // message loop. @@ -43,6 +43,6 @@ class TestAnimationDelegate : public AnimationDelegate { DISALLOW_COPY_AND_ASSIGN(TestAnimationDelegate); }; -} // namespace ui +} // namespace gfx -#endif // UI_BASE_ANIMATION_TEST_ANIMATION_DELEGATE_H_ +#endif // UI_GFX_ANIMATION_TEST_ANIMATION_DELEGATE_H_ diff --git a/chromium/ui/base/animation/throb_animation.cc b/chromium/ui/gfx/animation/throb_animation.cc index 72392a09161..0a88aa7d9c4 100644 --- a/chromium/ui/base/animation/throb_animation.cc +++ b/chromium/ui/gfx/animation/throb_animation.cc @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/animation/throb_animation.h" +#include "ui/gfx/animation/throb_animation.h" #include <limits> -namespace ui { +namespace gfx { static const int kDefaultThrobDurationMS = 400; @@ -82,4 +82,4 @@ void ThrobAnimation::ResetForSlide() { throbbing_ = false; } -} // namespace ui +} // namespace gfx diff --git a/chromium/ui/base/animation/throb_animation.h b/chromium/ui/gfx/animation/throb_animation.h index 4292eee81f1..8bea7f8799c 100644 --- a/chromium/ui/base/animation/throb_animation.h +++ b/chromium/ui/gfx/animation/throb_animation.h @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_ANIMATION_THROB_ANIMATION_H_ -#define UI_BASE_ANIMATION_THROB_ANIMATION_H_ +#ifndef UI_GFX_ANIMATION_THROB_ANIMATION_H_ +#define UI_GFX_ANIMATION_THROB_ANIMATION_H_ -#include "ui/base/animation/slide_animation.h" +#include "ui/gfx/animation/slide_animation.h" -namespace ui { +namespace gfx { // A subclass of SlideAnimation that can continually slide. All of the Animation // methods behave like that of SlideAnimation: transition to the next state. @@ -16,7 +16,7 @@ namespace ui { // // A ThrobAnimation has two durations: the duration used when behavior like // a SlideAnimation, and the duration used when throbbing. -class UI_EXPORT ThrobAnimation : public SlideAnimation { +class GFX_EXPORT ThrobAnimation : public SlideAnimation { public: explicit ThrobAnimation(AnimationDelegate* target); virtual ~ThrobAnimation() {} @@ -64,6 +64,6 @@ class UI_EXPORT ThrobAnimation : public SlideAnimation { DISALLOW_COPY_AND_ASSIGN(ThrobAnimation); }; -} // namespace ui +} // namespace gfx -#endif // UI_BASE_ANIMATION_THROB_ANIMATION_H_ +#endif // UI_GFX_ANIMATION_THROB_ANIMATION_H_ diff --git a/chromium/ui/base/animation/tween.cc b/chromium/ui/gfx/animation/tween.cc index ac6fa261fd5..4d1a6b3b260 100644 --- a/chromium/ui/base/animation/tween.cc +++ b/chromium/ui/gfx/animation/tween.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/animation/tween.h" +#include "ui/gfx/animation/tween.h" #include <math.h> @@ -12,7 +12,7 @@ #include "base/logging.h" -namespace ui { +namespace gfx { // static double Tween::CalculateValue(Tween::Type type, double state) { @@ -103,4 +103,4 @@ gfx::Transform Tween::ValueBetween(double value, return to_return; } -} // namespace ui +} // namespace gfx diff --git a/chromium/ui/base/animation/tween.h b/chromium/ui/gfx/animation/tween.h index 6e2f17977bc..0c1f7585ecf 100644 --- a/chromium/ui/base/animation/tween.h +++ b/chromium/ui/gfx/animation/tween.h @@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_ANIMATION_TWEEN_H_ -#define UI_BASE_ANIMATION_TWEEN_H_ +#ifndef UI_GFX_ANIMATION_TWEEN_H_ +#define UI_GFX_ANIMATION_TWEEN_H_ #include "base/basictypes.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/rect.h" #include "ui/gfx/transform.h" -namespace ui { +namespace gfx { -class UI_EXPORT Tween { +class GFX_EXPORT Tween { public: enum Type { LINEAR, // Linear. @@ -46,6 +46,6 @@ class UI_EXPORT Tween { DISALLOW_COPY_AND_ASSIGN(Tween); }; -} // namespace ui +} // namespace gfx -#endif // UI_BASE_ANIMATION_TWEEN_H_ +#endif // UI_GFX_ANIMATION_TWEEN_H_ diff --git a/chromium/ui/gfx/blit.h b/chromium/ui/gfx/blit.h index 616fda3c18d..f0668172c05 100644 --- a/chromium/ui/gfx/blit.h +++ b/chromium/ui/gfx/blit.h @@ -5,8 +5,8 @@ #ifndef UI_GFX_BLIT_H_ #define UI_GFX_BLIT_H_ +#include "ui/gfx/gfx_export.h" #include "ui/gfx/native_widget_types.h" -#include "ui/base/ui_export.h" class SkCanvas; diff --git a/chromium/ui/gfx/box_f.cc b/chromium/ui/gfx/box_f.cc index 107c5d691bf..efb57967145 100644 --- a/chromium/ui/gfx/box_f.cc +++ b/chromium/ui/gfx/box_f.cc @@ -4,6 +4,8 @@ #include "ui/gfx/box_f.h" +#include <algorithm> + #include "base/strings/stringprintf.h" namespace gfx { diff --git a/chromium/ui/gfx/break_list.h b/chromium/ui/gfx/break_list.h index 770386e9020..b55debf9688 100644 --- a/chromium/ui/gfx/break_list.h +++ b/chromium/ui/gfx/break_list.h @@ -10,7 +10,7 @@ #include "base/basictypes.h" #include "base/logging.h" -#include "ui/base/range/range.h" +#include "ui/gfx/range/range.h" namespace gfx { @@ -40,10 +40,11 @@ class BreakList { void SetValue(T value); // Adjust the breaks to apply |value| over the supplied |range|. - void ApplyValue(T value, const ui::Range& range); + void ApplyValue(T value, const Range& range); // Set the max position and trim any breaks at or beyond that position. void SetMax(size_t max); + size_t max() const { return max_; } // Get the break applicable to |position| (at or preceeding |position|). typename std::vector<Break>::iterator GetBreak(size_t position); @@ -51,7 +52,7 @@ class BreakList { // Get the range of the supplied break; returns the break's start position and // the next break's start position (or |max_| for the terminal break). - ui::Range GetRange(const typename BreakList<T>::const_iterator& i) const; + Range GetRange(const typename BreakList<T>::const_iterator& i) const; // Comparison functions for testing purposes. bool EqualsValueForTesting(T value) const; @@ -82,12 +83,12 @@ void BreakList<T>::SetValue(T value) { } template<class T> -void BreakList<T>::ApplyValue(T value, const ui::Range& range) { +void BreakList<T>::ApplyValue(T value, const Range& range) { if (!range.IsValid() || range.is_empty()) return; DCHECK(!breaks_.empty()); DCHECK(!range.is_reversed()); - DCHECK(ui::Range(0, max_).Contains(range)); + DCHECK(Range(0, max_).Contains(range)); // Erase any breaks in |range|, then add start and end breaks as needed. typename std::vector<Break>::iterator start = GetBreak(range.start()); @@ -135,10 +136,10 @@ typename std::vector<std::pair<size_t, T> >::const_iterator } template<class T> -ui::Range BreakList<T>::GetRange( +Range BreakList<T>::GetRange( const typename BreakList<T>::const_iterator& i) const { const typename BreakList<T>::const_iterator next = i + 1; - return ui::Range(i->first, next == breaks_.end() ? max_ : next->first); + return Range(i->first, next == breaks_.end() ? max_ : next->first); } template<class T> diff --git a/chromium/ui/gfx/break_list_unittest.cc b/chromium/ui/gfx/break_list_unittest.cc index 4acb0d264eb..5d4e39bbc05 100644 --- a/chromium/ui/gfx/break_list_unittest.cc +++ b/chromium/ui/gfx/break_list_unittest.cc @@ -6,7 +6,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkColor.h" -#include "ui/base/range/range.h" +#include "ui/gfx/range/range.h" namespace gfx { @@ -32,10 +32,10 @@ TEST_F(BreakListTest, ApplyValue) { breaks.SetMax(max); // Ensure ApplyValue is a no-op on invalid and empty ranges. - breaks.ApplyValue(true, ui::Range::InvalidRange()); + breaks.ApplyValue(true, Range::InvalidRange()); EXPECT_TRUE(breaks.EqualsValueForTesting(false)); for (size_t i = 0; i < 3; ++i) { - breaks.ApplyValue(true, ui::Range(i, i)); + breaks.ApplyValue(true, Range(i, i)); EXPECT_TRUE(breaks.EqualsValueForTesting(false)); } @@ -45,7 +45,7 @@ TEST_F(BreakListTest, ApplyValue) { expected.push_back(std::pair<size_t, bool>(2, true)); expected.push_back(std::pair<size_t, bool>(3, false)); for (size_t i = 0; i < 2; ++i) { - breaks.ApplyValue(true, ui::Range(2, 3)); + breaks.ApplyValue(true, Range(2, 3)); EXPECT_TRUE(breaks.EqualsForTesting(expected)); } @@ -54,43 +54,43 @@ TEST_F(BreakListTest, ApplyValue) { EXPECT_TRUE(breaks.EqualsValueForTesting(true)); // Ensure applying a value over [0, |max|) is the same as setting a value. - breaks.ApplyValue(false, ui::Range(0, max)); + breaks.ApplyValue(false, Range(0, max)); EXPECT_TRUE(breaks.EqualsValueForTesting(false)); // Ensure applying a value that is already applied has no effect. - breaks.ApplyValue(false, ui::Range(0, 2)); - breaks.ApplyValue(false, ui::Range(3, 6)); - breaks.ApplyValue(false, ui::Range(7, max)); + breaks.ApplyValue(false, Range(0, 2)); + breaks.ApplyValue(false, Range(3, 6)); + breaks.ApplyValue(false, Range(7, max)); EXPECT_TRUE(breaks.EqualsValueForTesting(false)); // Ensure applying an identical neighboring value merges the ranges. - breaks.ApplyValue(true, ui::Range(0, 3)); - breaks.ApplyValue(true, ui::Range(3, 6)); - breaks.ApplyValue(true, ui::Range(6, max)); + breaks.ApplyValue(true, Range(0, 3)); + breaks.ApplyValue(true, Range(3, 6)); + breaks.ApplyValue(true, Range(6, max)); EXPECT_TRUE(breaks.EqualsValueForTesting(true)); // Ensure applying a value with the same range overrides the ranged value. - breaks.ApplyValue(false, ui::Range(2, 3)); - breaks.ApplyValue(true, ui::Range(2, 3)); + breaks.ApplyValue(false, Range(2, 3)); + breaks.ApplyValue(true, Range(2, 3)); EXPECT_TRUE(breaks.EqualsValueForTesting(true)); // Ensure applying a value with a containing range overrides contained values. - breaks.ApplyValue(false, ui::Range(0, 1)); - breaks.ApplyValue(false, ui::Range(2, 3)); - breaks.ApplyValue(true, ui::Range(0, 3)); + breaks.ApplyValue(false, Range(0, 1)); + breaks.ApplyValue(false, Range(2, 3)); + breaks.ApplyValue(true, Range(0, 3)); EXPECT_TRUE(breaks.EqualsValueForTesting(true)); - breaks.ApplyValue(false, ui::Range(4, 5)); - breaks.ApplyValue(false, ui::Range(6, 7)); - breaks.ApplyValue(false, ui::Range(8, 9)); - breaks.ApplyValue(true, ui::Range(4, 9)); + breaks.ApplyValue(false, Range(4, 5)); + breaks.ApplyValue(false, Range(6, 7)); + breaks.ApplyValue(false, Range(8, 9)); + breaks.ApplyValue(true, Range(4, 9)); EXPECT_TRUE(breaks.EqualsValueForTesting(true)); // Ensure applying various overlapping values yields the intended results. - breaks.ApplyValue(false, ui::Range(1, 4)); - breaks.ApplyValue(false, ui::Range(5, 8)); - breaks.ApplyValue(true, ui::Range(0, 2)); - breaks.ApplyValue(true, ui::Range(3, 6)); - breaks.ApplyValue(true, ui::Range(7, max)); + breaks.ApplyValue(false, Range(1, 4)); + breaks.ApplyValue(false, Range(5, 8)); + breaks.ApplyValue(true, Range(0, 2)); + breaks.ApplyValue(true, Range(3, 6)); + breaks.ApplyValue(true, Range(7, max)); std::vector<std::pair<size_t, bool> > overlap; overlap.push_back(std::pair<size_t, bool>(0, true)); overlap.push_back(std::pair<size_t, bool>(2, false)); @@ -104,9 +104,9 @@ TEST_F(BreakListTest, SetMax) { // Ensure values adjust to accommodate max position changes. BreakList<bool> breaks(false); breaks.SetMax(9); - breaks.ApplyValue(true, ui::Range(0, 2)); - breaks.ApplyValue(true, ui::Range(3, 6)); - breaks.ApplyValue(true, ui::Range(7, 9)); + breaks.ApplyValue(true, Range(0, 2)); + breaks.ApplyValue(true, Range(3, 6)); + breaks.ApplyValue(true, Range(7, 9)); std::vector<std::pair<size_t, bool> > expected; expected.push_back(std::pair<size_t, bool>(0, true)); @@ -134,25 +134,25 @@ TEST_F(BreakListTest, SetMax) { TEST_F(BreakListTest, GetBreakAndRange) { BreakList<bool> breaks(false); breaks.SetMax(8); - breaks.ApplyValue(true, ui::Range(1, 2)); - breaks.ApplyValue(true, ui::Range(4, 6)); + breaks.ApplyValue(true, Range(1, 2)); + breaks.ApplyValue(true, Range(4, 6)); struct { size_t position; size_t break_index; - ui::Range range; + Range range; } cases[] = { - { 0, 0, ui::Range(0, 1) }, - { 1, 1, ui::Range(1, 2) }, - { 2, 2, ui::Range(2, 4) }, - { 3, 2, ui::Range(2, 4) }, - { 4, 3, ui::Range(4, 6) }, - { 5, 3, ui::Range(4, 6) }, - { 6, 4, ui::Range(6, 8) }, - { 7, 4, ui::Range(6, 8) }, + { 0, 0, Range(0, 1) }, + { 1, 1, Range(1, 2) }, + { 2, 2, Range(2, 4) }, + { 3, 2, Range(2, 4) }, + { 4, 3, Range(4, 6) }, + { 5, 3, Range(4, 6) }, + { 6, 4, Range(6, 8) }, + { 7, 4, Range(6, 8) }, // Positions at or beyond the max simply return the last break and range. - { 8, 4, ui::Range(6, 8) }, - { 9, 4, ui::Range(6, 8) }, + { 8, 4, Range(6, 8) }, + { 9, 4, Range(6, 8) }, }; diff --git a/chromium/ui/gfx/canvas.cc b/chromium/ui/gfx/canvas.cc index 2b0f5046cf0..b59d2a0d888 100644 --- a/chromium/ui/gfx/canvas.cc +++ b/chromium/ui/gfx/canvas.cc @@ -11,7 +11,7 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/effects/SkGradientShader.h" #include "ui/gfx/canvas.h" -#include "ui/gfx/font.h" +#include "ui/gfx/font_list.h" #include "ui/gfx/rect.h" #include "ui/gfx/size_conversions.h" #include "ui/gfx/skia_util.h" @@ -23,13 +23,11 @@ namespace gfx { -Canvas::Canvas(const gfx::Size& size, - ui::ScaleFactor scale_factor, - bool is_opaque) - : scale_factor_(scale_factor), - canvas_(NULL) { - gfx::Size pixel_size = gfx::ToCeiledSize( - gfx::ScaleSize(size, ui::GetScaleFactorScale(scale_factor))); +Canvas::Canvas(const Size& size, ui::ScaleFactor scale_factor, bool is_opaque) + : scale_factor_(scale_factor), + canvas_(NULL) { + Size pixel_size = ToCeiledSize( + ScaleSize(size, ui::GetScaleFactorScale(scale_factor))); owned_canvas_ = skia::AdoptRef(skia::CreatePlatformCanvas(pixel_size.width(), pixel_size.height(), is_opaque)); @@ -45,7 +43,7 @@ Canvas::Canvas(const gfx::Size& size, canvas_->scale(scale, scale); } -Canvas::Canvas(const gfx::ImageSkiaRep& image_rep, bool is_opaque) +Canvas::Canvas(const ImageSkiaRep& image_rep, bool is_opaque) : scale_factor_(image_rep.scale_factor()), owned_canvas_(skia::AdoptRef( skia::CreatePlatformCanvas(image_rep.pixel_width(), @@ -54,7 +52,7 @@ Canvas::Canvas(const gfx::ImageSkiaRep& image_rep, bool is_opaque) canvas_(owned_canvas_.get()) { SkScalar scale = SkFloatToScalar(ui::GetScaleFactorScale(scale_factor_)); canvas_->scale(scale, scale); - DrawImageInt(gfx::ImageSkia(image_rep), 0, 0); + DrawImageInt(ImageSkia(image_rep), 0, 0); } Canvas::Canvas() @@ -72,12 +70,12 @@ Canvas* Canvas::CreateCanvasWithoutScaling(SkCanvas* canvas, return new Canvas(canvas, scale_factor); } -void Canvas::RecreateBackingCanvas(const gfx::Size& size, +void Canvas::RecreateBackingCanvas(const Size& size, ui::ScaleFactor scale_factor, bool is_opaque) { scale_factor_ = scale_factor; - gfx::Size pixel_size = gfx::ToFlooredSize( - gfx::ScaleSize(size, ui::GetScaleFactorScale(scale_factor))); + Size pixel_size = ToFlooredSize( + ScaleSize(size, ui::GetScaleFactorScale(scale_factor))); owned_canvas_ = skia::AdoptRef(skia::CreatePlatformCanvas(pixel_size.width(), pixel_size.height(), is_opaque)); @@ -87,9 +85,27 @@ void Canvas::RecreateBackingCanvas(const gfx::Size& size, } // static -int Canvas::GetStringWidth(const base::string16& text, const gfx::Font& font) { +void Canvas::SizeStringInt(const base::string16& text, + const Font& font, + int* width, + int* height, + int line_height, + int flags) { + SizeStringInt(text, FontList(font), width, height, line_height, flags); +} + +// static +int Canvas::GetStringWidth(const base::string16& text, + const FontList& font_list) { + int width = 0, height = 0; + SizeStringInt(text, font_list, &width, &height, 0, NO_ELLIPSIS); + return width; +} + +// static +int Canvas::GetStringWidth(const base::string16& text, const Font& font) { int width = 0, height = 0; - Canvas::SizeStringInt(text, font, &width, &height, 0, NO_ELLIPSIS); + SizeStringInt(text, FontList(font), &width, &height, 0, NO_ELLIPSIS); return width; } @@ -98,7 +114,20 @@ int Canvas::DefaultCanvasTextAlignment() { return base::i18n::IsRTL() ? TEXT_ALIGN_RIGHT : TEXT_ALIGN_LEFT; } -gfx::ImageSkiaRep Canvas::ExtractImageRep() const { +void Canvas::DrawStringWithHalo(const base::string16& text, + const Font& font, + SkColor text_color, + SkColor halo_color_in, + int x, + int y, + int w, + int h, + int flags) { + DrawStringRectWithHalo(text, FontList(font), text_color, halo_color_in, + Rect(x, y, w, h), flags); +} + +ImageSkiaRep Canvas::ExtractImageRep() const { const SkBitmap& device_bitmap = canvas_->getDevice()->accessBitmap(false); // Make a bitmap to return, and a canvas to draw into it. We don't just want @@ -107,10 +136,10 @@ gfx::ImageSkiaRep Canvas::ExtractImageRep() const { SkBitmap result; device_bitmap.copyTo(&result, SkBitmap::kARGB_8888_Config); - return gfx::ImageSkiaRep(result, scale_factor_); + return ImageSkiaRep(result, scale_factor_); } -void Canvas::DrawDashedRect(const gfx::Rect& rect, SkColor color) { +void Canvas::DrawDashedRect(const Rect& rect, SkColor color) { // Create a 2D bitmap containing alternating on/off pixels - we do this // so that you never get two pixels of the same color around the edges // of the focus rect (this may mean that opposing edges of the rect may @@ -149,11 +178,11 @@ void Canvas::DrawDashedRect(const gfx::Rect& rect, SkColor color) { SkPaint paint; paint.setShader(shader.get()); - DrawRect(gfx::Rect(rect.x(), rect.y(), rect.width(), 1), paint); - DrawRect(gfx::Rect(rect.x(), rect.y() + rect.height() - 1, rect.width(), 1), + DrawRect(Rect(rect.x(), rect.y(), rect.width(), 1), paint); + DrawRect(Rect(rect.x(), rect.y() + rect.height() - 1, rect.width(), 1), paint); - DrawRect(gfx::Rect(rect.x(), rect.y(), 1, rect.height()), paint); - DrawRect(gfx::Rect(rect.x() + rect.width() - 1, rect.y(), 1, rect.height()), + DrawRect(Rect(rect.x(), rect.y(), 1, rect.height()), paint); + DrawRect(Rect(rect.x() + rect.width() - 1, rect.y(), 1, rect.height()), paint); } @@ -166,8 +195,8 @@ void Canvas::SaveLayerAlpha(uint8 alpha) { } -void Canvas::SaveLayerAlpha(uint8 alpha, const gfx::Rect& layer_bounds) { - SkRect bounds(gfx::RectToSkRect(layer_bounds)); +void Canvas::SaveLayerAlpha(uint8 alpha, const Rect& layer_bounds) { + SkRect bounds(RectToSkRect(layer_bounds)); canvas_->saveLayerAlpha(&bounds, alpha); } @@ -175,22 +204,22 @@ void Canvas::Restore() { canvas_->restore(); } -bool Canvas::ClipRect(const gfx::Rect& rect) { - return canvas_->clipRect(gfx::RectToSkRect(rect)); +bool Canvas::ClipRect(const Rect& rect) { + return canvas_->clipRect(RectToSkRect(rect)); } bool Canvas::ClipPath(const SkPath& path) { return canvas_->clipPath(path); } -bool Canvas::GetClipBounds(gfx::Rect* bounds) { +bool Canvas::GetClipBounds(Rect* bounds) { SkRect out; bool has_non_empty_clip = canvas_->getClipBounds(&out); bounds->SetRect(out.left(), out.top(), out.width(), out.height()); return has_non_empty_clip; } -void Canvas::Translate(const gfx::Vector2d& offset) { +void Canvas::Translate(const Vector2d& offset) { canvas_->translate(SkIntToScalar(offset.x()), SkIntToScalar(offset.y())); } @@ -206,11 +235,11 @@ void Canvas::DrawColor(SkColor color, SkXfermode::Mode mode) { canvas_->drawColor(color, mode); } -void Canvas::FillRect(const gfx::Rect& rect, SkColor color) { +void Canvas::FillRect(const Rect& rect, SkColor color) { FillRect(rect, color, SkXfermode::kSrcOver_Mode); } -void Canvas::FillRect(const gfx::Rect& rect, +void Canvas::FillRect(const Rect& rect, SkColor color, SkXfermode::Mode mode) { SkPaint paint; @@ -220,11 +249,11 @@ void Canvas::FillRect(const gfx::Rect& rect, DrawRect(rect, paint); } -void Canvas::DrawRect(const gfx::Rect& rect, SkColor color) { +void Canvas::DrawRect(const Rect& rect, SkColor color) { DrawRect(rect, color, SkXfermode::kSrcOver_Mode); } -void Canvas::DrawRect(const gfx::Rect& rect, +void Canvas::DrawRect(const Rect& rect, SkColor color, SkXfermode::Mode mode) { SkPaint paint; @@ -239,38 +268,34 @@ void Canvas::DrawRect(const gfx::Rect& rect, DrawRect(rect, paint); } -void Canvas::DrawRect(const gfx::Rect& rect, const SkPaint& paint) { +void Canvas::DrawRect(const Rect& rect, const SkPaint& paint) { canvas_->drawIRect(RectToSkIRect(rect), paint); } -void Canvas::DrawPoint(const gfx::Point& p1, const SkPaint& paint) { +void Canvas::DrawPoint(const Point& p1, const SkPaint& paint) { canvas_->drawPoint(SkIntToScalar(p1.x()), SkIntToScalar(p1.y()), paint); } -void Canvas::DrawLine(const gfx::Point& p1, - const gfx::Point& p2, - SkColor color) { +void Canvas::DrawLine(const Point& p1, const Point& p2, SkColor color) { SkPaint paint; paint.setColor(color); paint.setStrokeWidth(SkIntToScalar(1)); DrawLine(p1, p2, paint); } -void Canvas::DrawLine(const gfx::Point& p1, - const gfx::Point& p2, - const SkPaint& paint) { +void Canvas::DrawLine(const Point& p1, const Point& p2, const SkPaint& paint) { canvas_->drawLine(SkIntToScalar(p1.x()), SkIntToScalar(p1.y()), SkIntToScalar(p2.x()), SkIntToScalar(p2.y()), paint); } -void Canvas::DrawCircle(const gfx::Point& center_point, +void Canvas::DrawCircle(const Point& center_point, int radius, const SkPaint& paint) { canvas_->drawCircle(SkIntToScalar(center_point.x()), SkIntToScalar(center_point.y()), SkIntToScalar(radius), paint); } -void Canvas::DrawRoundRect(const gfx::Rect& rect, +void Canvas::DrawRoundRect(const Rect& rect, int radius, const SkPaint& paint) { canvas_->drawRoundRect(RectToSkRect(rect), SkIntToScalar(radius), @@ -281,25 +306,26 @@ void Canvas::DrawPath(const SkPath& path, const SkPaint& paint) { canvas_->drawPath(path, paint); } -void Canvas::DrawFocusRect(const gfx::Rect& rect) { +void Canvas::DrawFocusRect(const Rect& rect) { DrawDashedRect(rect, SK_ColorGRAY); } -void Canvas::DrawImageInt(const gfx::ImageSkia& image, int x, int y) { +void Canvas::DrawImageInt(const ImageSkia& image, int x, int y) { SkPaint paint; DrawImageInt(image, x, y, paint); } -void Canvas::DrawImageInt(const gfx::ImageSkia& image, int x, int y, uint8 a) { +void Canvas::DrawImageInt(const ImageSkia& image, int x, int y, uint8 a) { SkPaint paint; paint.setAlpha(a); DrawImageInt(image, x, y, paint); } -void Canvas::DrawImageInt(const gfx::ImageSkia& image, - int x, int y, +void Canvas::DrawImageInt(const ImageSkia& image, + int x, + int y, const SkPaint& paint) { - const gfx::ImageSkiaRep& image_rep = GetImageRepToPaint(image); + const ImageSkiaRep& image_rep = GetImageRepToPaint(image); if (image_rep.is_null()) return; const SkBitmap& bitmap = image_rep.sk_bitmap(); @@ -315,18 +341,30 @@ void Canvas::DrawImageInt(const gfx::ImageSkia& image, canvas_->restore(); } -void Canvas::DrawImageInt(const gfx::ImageSkia& image, - int src_x, int src_y, int src_w, int src_h, - int dest_x, int dest_y, int dest_w, int dest_h, +void Canvas::DrawImageInt(const ImageSkia& image, + int src_x, + int src_y, + int src_w, + int src_h, + int dest_x, + int dest_y, + int dest_w, + int dest_h, bool filter) { SkPaint p; DrawImageInt(image, src_x, src_y, src_w, src_h, dest_x, dest_y, dest_w, dest_h, filter, p); } -void Canvas::DrawImageInt(const gfx::ImageSkia& image, - int src_x, int src_y, int src_w, int src_h, - int dest_x, int dest_y, int dest_w, int dest_h, +void Canvas::DrawImageInt(const ImageSkia& image, + int src_x, + int src_y, + int src_w, + int src_h, + int dest_x, + int dest_y, + int dest_w, + int dest_h, bool filter, const SkPaint& paint) { DLOG_ASSERT(src_x + src_w < std::numeric_limits<int16_t>::max() && @@ -342,7 +380,7 @@ void Canvas::DrawImageInt(const gfx::ImageSkia& image, float user_scale_x = static_cast<float>(dest_w) / src_w; float user_scale_y = static_cast<float>(dest_h) / src_h; - const gfx::ImageSkiaRep& image_rep = GetImageRepToPaint(image, + const ImageSkiaRep& image_rep = GetImageRepToPaint(image, user_scale_x, user_scale_y); if (image_rep.is_null()) return; @@ -373,7 +411,7 @@ void Canvas::DrawImageInt(const gfx::ImageSkia& image, shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y)); shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y)); - skia::RefPtr<SkShader> shader = gfx::CreateImageRepShader( + skia::RefPtr<SkShader> shader = CreateImageRepShader( image_rep, SkShader::kRepeat_TileMode, shader_scale); @@ -388,18 +426,18 @@ void Canvas::DrawImageInt(const gfx::ImageSkia& image, canvas_->drawRect(dest_rect, p); } -void Canvas::DrawImageInPath(const gfx::ImageSkia& image, +void Canvas::DrawImageInPath(const ImageSkia& image, int x, int y, const SkPath& path, const SkPaint& paint) { - const gfx::ImageSkiaRep& image_rep = GetImageRepToPaint(image); + const ImageSkiaRep& image_rep = GetImageRepToPaint(image); if (image_rep.is_null()) return; SkMatrix matrix; matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y)); - skia::RefPtr<SkShader> shader = gfx::CreateImageRepShader( + skia::RefPtr<SkShader> shader = CreateImageRepShader( image_rep, SkShader::kRepeat_TileMode, matrix); @@ -409,55 +447,96 @@ void Canvas::DrawImageInPath(const gfx::ImageSkia& image, canvas_->drawPath(path, p); } +void Canvas::DrawStringRect(const base::string16& text, + const FontList& font_list, + SkColor color, + const Rect& display_rect) { + DrawStringRectWithFlags(text, font_list, color, display_rect, + DefaultCanvasTextAlignment()); +} + +void Canvas::DrawStringRectWithFlags(const base::string16& text, + const FontList& font_list, + SkColor color, + const Rect& display_rect, + int flags) { + DrawStringRectWithShadows(text, font_list, color, display_rect, 0, flags, + ShadowValues()); +} + void Canvas::DrawStringInt(const base::string16& text, - const gfx::Font& font, + const Font& font, SkColor color, - int x, int y, int w, int h) { + int x, + int y, + int w, + int h) { DrawStringInt(text, font, color, x, y, w, h, DefaultCanvasTextAlignment()); } void Canvas::DrawStringInt(const base::string16& text, - const gfx::Font& font, + const Font& font, SkColor color, - const gfx::Rect& display_rect) { + const Rect& display_rect) { DrawStringInt(text, font, color, display_rect.x(), display_rect.y(), display_rect.width(), display_rect.height()); } void Canvas::DrawStringInt(const base::string16& text, - const gfx::Font& font, + const Font& font, SkColor color, - int x, int y, int w, int h, + int x, + int y, + int w, + int h, int flags) { - DrawStringWithShadows(text, - font, - color, - gfx::Rect(x, y, w, h), - 0, - flags, + DrawStringWithShadows(text, font, color, Rect(x, y, w, h), 0, flags, ShadowValues()); } -void Canvas::TileImageInt(const gfx::ImageSkia& image, - int x, int y, int w, int h) { +void Canvas::DrawStringWithShadows(const base::string16& text, + const Font& font, + SkColor color, + const Rect& text_bounds, + int line_height, + int flags, + const ShadowValues& shadows) { + DrawStringRectWithShadows(text, FontList(font), color, text_bounds, + line_height, flags, shadows); +} + +void Canvas::TileImageInt(const ImageSkia& image, + int x, + int y, + int w, + int h) { TileImageInt(image, 0, 0, x, y, w, h); } -void Canvas::TileImageInt(const gfx::ImageSkia& image, - int src_x, int src_y, - int dest_x, int dest_y, int w, int h) { +void Canvas::TileImageInt(const ImageSkia& image, + int src_x, + int src_y, + int dest_x, + int dest_y, + int w, + int h) { TileImageInt(image, src_x, src_y, 1.0f, 1.0f, dest_x, dest_y, w, h); } -void Canvas::TileImageInt(const gfx::ImageSkia& image, - int src_x, int src_y, - float tile_scale_x, float tile_scale_y, - int dest_x, int dest_y, int w, int h) { +void Canvas::TileImageInt(const ImageSkia& image, + int src_x, + int src_y, + float tile_scale_x, + float tile_scale_y, + int dest_x, + int dest_y, + int w, + int h) { if (!IntersectsClipRectInt(dest_x, dest_y, w, h)) return; - const gfx::ImageSkiaRep& image_rep = GetImageRepToPaint(image, - tile_scale_x, tile_scale_y); + const ImageSkiaRep& image_rep = GetImageRepToPaint( + image, tile_scale_x, tile_scale_y); if (image_rep.is_null()) return; @@ -467,7 +546,7 @@ void Canvas::TileImageInt(const gfx::ImageSkia& image, shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y)); shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y)); - skia::RefPtr<SkShader> shader = gfx::CreateImageRepShader( + skia::RefPtr<SkShader> shader = CreateImageRepShader( image_rep, SkShader::kRepeat_TileMode, shader_scale); @@ -483,7 +562,7 @@ void Canvas::TileImageInt(const gfx::ImageSkia& image, canvas_->drawRect(dest_rect, paint); } -gfx::NativeDrawingContext Canvas::BeginPlatformPaint() { +NativeDrawingContext Canvas::BeginPlatformPaint() { return skia::BeginPlatformPaint(canvas_); } @@ -509,21 +588,20 @@ bool Canvas::IntersectsClipRectInt(int x, int y, int w, int h) { SkIntToScalar(y + h)); } -bool Canvas::IntersectsClipRect(const gfx::Rect& rect) { +bool Canvas::IntersectsClipRect(const Rect& rect) { return IntersectsClipRectInt(rect.x(), rect.y(), rect.width(), rect.height()); } -const gfx::ImageSkiaRep& Canvas::GetImageRepToPaint( - const gfx::ImageSkia& image) const { +const ImageSkiaRep& Canvas::GetImageRepToPaint(const ImageSkia& image) const { return GetImageRepToPaint(image, 1.0f, 1.0f); } -const gfx::ImageSkiaRep& Canvas::GetImageRepToPaint( - const gfx::ImageSkia& image, +const ImageSkiaRep& Canvas::GetImageRepToPaint( + const ImageSkia& image, float user_additional_scale_x, float user_additional_scale_y) const { - const gfx::ImageSkiaRep& image_rep = image.GetRepresentation(scale_factor_); + const ImageSkiaRep& image_rep = image.GetRepresentation(scale_factor_); if (!image_rep.is_null()) { SkMatrix m = canvas_->getTotalMatrix(); diff --git a/chromium/ui/gfx/canvas.h b/chromium/ui/gfx/canvas.h index 8baa45c11e3..c8996a234a8 100644 --- a/chromium/ui/gfx/canvas.h +++ b/chromium/ui/gfx/canvas.h @@ -20,6 +20,7 @@ namespace gfx { class Rect; class Font; +class FontList; class Point; class Size; class Transform; @@ -95,17 +96,15 @@ class UI_EXPORT Canvas { // Creates canvas with provided DIP |size| and |scale_factor|. // If this canvas is not opaque, it's explicitly cleared to transparent before // being returned. - Canvas(const gfx::Size& size, - ui::ScaleFactor scale_factor, - bool is_opaque); + Canvas(const Size& size, ui::ScaleFactor scale_factor, bool is_opaque); // Constructs a canvas with the size and the scale factor of the // provided |image_rep|, and draws the |image_rep| into it. - Canvas(const gfx::ImageSkiaRep& image_rep, bool is_opaque); + Canvas(const ImageSkiaRep& image_rep, bool is_opaque); virtual ~Canvas(); - // Creates a gfx::Canvas backed by an |sk_canvas| with |scale_factor|. + // Creates a Canvas backed by an |sk_canvas| with |scale_factor|. // |sk_canvas| is assumed to be already scaled based on |scale_factor| // so no additional scaling is applied. static Canvas* CreateCanvasWithoutScaling(SkCanvas* sk_canvas, @@ -117,36 +116,47 @@ class UI_EXPORT Canvas { // canvas after having initialized the canvas. // TODO(pkotwicz): Push the scale factor into skia::PlatformCanvas such that // this method can be private. - void RecreateBackingCanvas(const gfx::Size& size, + void RecreateBackingCanvas(const Size& size, ui::ScaleFactor scale_factor, bool is_opaque); - // Compute the size required to draw some text with the provided font. + // Compute the size required to draw some text with the provided fonts. // Attempts to fit the text with the provided width and height. Increases // height and then width as needed to make the text fit. This method // supports multiple lines. On Skia only a line_height can be specified and // specifying a 0 value for it will cause the default height to be used. static void SizeStringInt(const base::string16& text, - const gfx::Font& font, - int* width, int* height, + const FontList& font_list, + int* width, + int* height, + int line_height, + int flags); + // Obsolete version. Use the above version which takes FontList. + static void SizeStringInt(const base::string16& text, + const Font& font, + int* width, + int* height, int line_height, int flags); // Returns the number of horizontal pixels needed to display the specified - // |text| with |font|. - static int GetStringWidth(const base::string16& text, const gfx::Font& font); + // |text| with |font_list|. + static int GetStringWidth(const base::string16& text, + const FontList& font_list); + // Obsolete version. Use the above version which takes FontList. + static int GetStringWidth(const base::string16& text, const Font& font); // Returns the default text alignment to be used when drawing text on a - // gfx::Canvas based on the directionality of the system locale language. - // This function is used by gfx::Canvas::DrawStringInt when the text alignment + // Canvas based on the directionality of the system locale language. + // This function is used by Canvas::DrawStringInt when the text alignment // is not specified. // - // This function returns either gfx::Canvas::TEXT_ALIGN_LEFT or - // gfx::Canvas::TEXT_ALIGN_RIGHT. + // This function returns either Canvas::TEXT_ALIGN_LEFT or + // Canvas::TEXT_ALIGN_RIGHT. static int DefaultCanvasTextAlignment(); // Draws text with a 1-pixel halo around it of the given color. - // On Windows, it allows ClearType to be drawn to an otherwise transparenct + // On Windows, it allows ClearType to be drawn to an otherwise transparent // bitmap for drag images. Drag images have only 1-bit of transparency, so // we don't do any fancy blurring. // On Linux, text with halo is created by stroking it with 2px |halo_color| @@ -154,18 +164,28 @@ class UI_EXPORT Canvas { // On Mac, NOTIMPLEMENTED. // TODO(dhollowa): Skia-native implementation is underway. Cut over to // that when ready. http::/crbug.com/109946 + void DrawStringRectWithHalo(const base::string16& text, + const FontList& font_list, + SkColor text_color, + SkColor halo_color, + const Rect& display_rect, + int flags); + // Obsolete version. Use the above version which takes FontList. void DrawStringWithHalo(const base::string16& text, - const gfx::Font& font, + const Font& font, SkColor text_color, SkColor halo_color, - int x, int y, int w, int h, + int x, + int y, + int w, + int h, int flags); // Extracts an ImageSkiaRep from the contents of this canvas. - gfx::ImageSkiaRep ExtractImageRep() const; + ImageSkiaRep ExtractImageRep() const; // Draws a dashed rectangle of the specified color. - void DrawDashedRect(const gfx::Rect& rect, SkColor color); + void DrawDashedRect(const Rect& rect, SkColor color); // Saves a copy of the drawing state onto a stack, operating on this copy // until a balanced call to Restore() is made. @@ -176,7 +196,7 @@ class UI_EXPORT Canvas { // |layer_bounds| are the bounds of the layer relative to the current // transform. void SaveLayerAlpha(uint8 alpha); - void SaveLayerAlpha(uint8 alpha, const gfx::Rect& layer_bounds); + void SaveLayerAlpha(uint8 alpha, const Rect& layer_bounds); // Restores the drawing state after a call to Save*(). It is an error to // call Restore() more times than Save*(). @@ -184,7 +204,7 @@ class UI_EXPORT Canvas { // Adds |rect| to the current clip. Returns true if the resulting clip is // non-empty. - bool ClipRect(const gfx::Rect& rect); + bool ClipRect(const Rect& rect); // Adds |path| to the current clip. Returns true if the resulting clip is // non-empty. @@ -192,9 +212,9 @@ class UI_EXPORT Canvas { // Returns the bounds of the current clip (in local coordinates) in the // |bounds| parameter, and returns true if it is non empty. - bool GetClipBounds(gfx::Rect* bounds); + bool GetClipBounds(Rect* bounds); - void Translate(const gfx::Vector2d& offset); + void Translate(const Vector2d& offset); void Scale(int x_scale, int y_scale); @@ -208,45 +228,43 @@ class UI_EXPORT Canvas { // Fills |rect| with |color| using a transfer mode of // SkXfermode::kSrcOver_Mode. - void FillRect(const gfx::Rect& rect, SkColor color); + void FillRect(const Rect& rect, SkColor color); // Fills |rect| with the specified |color| and |mode|. - void FillRect(const gfx::Rect& rect, SkColor color, SkXfermode::Mode mode); + void FillRect(const Rect& rect, SkColor color, SkXfermode::Mode mode); // Draws a single pixel rect in the specified region with the specified // color, using a transfer mode of SkXfermode::kSrcOver_Mode. // // NOTE: if you need a single pixel line, use DrawLine. - void DrawRect(const gfx::Rect& rect, SkColor color); + void DrawRect(const Rect& rect, SkColor color); // Draws a single pixel rect in the specified region with the specified // color and transfer mode. // // NOTE: if you need a single pixel line, use DrawLine. - void DrawRect(const gfx::Rect& rect, SkColor color, SkXfermode::Mode mode); + void DrawRect(const Rect& rect, SkColor color, SkXfermode::Mode mode); // Draws the given rectangle with the given |paint| parameters. - void DrawRect(const gfx::Rect& rect, const SkPaint& paint); + void DrawRect(const Rect& rect, const SkPaint& paint); // Draw the given point with the given |paint| parameters. - void DrawPoint(const gfx::Point& p, const SkPaint& paint); + void DrawPoint(const Point& p, const SkPaint& paint); // Draws a single pixel line with the specified color. - void DrawLine(const gfx::Point& p1, const gfx::Point& p2, SkColor color); + void DrawLine(const Point& p1, const Point& p2, SkColor color); // Draws a line with the given |paint| parameters. - void DrawLine(const gfx::Point& p1, - const gfx::Point& p2, - const SkPaint& paint); + void DrawLine(const Point& p1, const Point& p2, const SkPaint& paint); // Draws a circle with the given |paint| parameters. - void DrawCircle(const gfx::Point& center_point, + void DrawCircle(const Point& center_point, int radius, const SkPaint& paint); // Draws the given rectangle with rounded corners of |radius| using the // given |paint| parameters. - void DrawRoundRect(const gfx::Rect& rect, int radius, const SkPaint& paint); + void DrawRoundRect(const Rect& rect, int radius, const SkPaint& paint); // Draws the given path using the given |paint| parameters. void DrawPath(const SkPath& path, const SkPaint& paint); @@ -255,19 +273,20 @@ class UI_EXPORT Canvas { // corner of the bitmap is rendered at the specified location. // Parameters are specified relative to current canvas scale not in pixels. // Thus, x is 2 pixels if canvas scale = 2 & |x| = 1. - void DrawImageInt(const gfx::ImageSkia&, int x, int y); + void DrawImageInt(const ImageSkia&, int x, int y); // Helper for DrawImageInt(..., paint) that constructs a temporary paint and // calls paint.setAlpha(alpha). - void DrawImageInt(const gfx::ImageSkia&, int x, int y, uint8 alpha); + void DrawImageInt(const ImageSkia&, int x, int y, uint8 alpha); // Draws an image with the origin at the specified location, using the // specified paint. The upper left corner of the bitmap is rendered at the // specified location. // Parameters are specified relative to current canvas scale not in pixels. // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1. - void DrawImageInt(const gfx::ImageSkia& image, - int x, int y, + void DrawImageInt(const ImageSkia& image, + int x, + int y, const SkPaint& paint); // Draws a portion of an image in the specified location. The src parameters @@ -282,13 +301,25 @@ class UI_EXPORT Canvas { // An optional custom SkPaint can be provided. // Parameters are specified relative to current canvas scale not in pixels. // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1. - void DrawImageInt(const gfx::ImageSkia& image, - int src_x, int src_y, int src_w, int src_h, - int dest_x, int dest_y, int dest_w, int dest_h, + void DrawImageInt(const ImageSkia& image, + int src_x, + int src_y, + int src_w, + int src_h, + int dest_x, + int dest_y, + int dest_w, + int dest_h, bool filter); - void DrawImageInt(const gfx::ImageSkia& image, - int src_x, int src_y, int src_w, int src_h, - int dest_x, int dest_y, int dest_w, int dest_h, + void DrawImageInt(const ImageSkia& image, + int src_x, + int src_y, + int src_w, + int src_h, + int dest_x, + int dest_y, + int dest_w, + int dest_h, bool filter, const SkPaint& paint); @@ -296,59 +327,96 @@ class UI_EXPORT Canvas { // |path|. // Parameters are specified relative to current canvas scale not in pixels. // Thus, x is 2 pixels if canvas scale = 2 & |x| = 1. - void DrawImageInPath(const gfx::ImageSkia& image, + void DrawImageInPath(const ImageSkia& image, int x, int y, const SkPath& path, const SkPaint& paint); - // Draws text with the specified color, font and location. The text is + // Draws text with the specified color, fonts and location. The text is // aligned to the left, vertically centered, clipped to the region. If the // text is too big, it is truncated and '...' is added to the end. + void DrawStringRect(const base::string16& text, + const FontList& font_list, + SkColor color, + const Rect& display_rect); + // Obsolete versions. Use the above versions which take FontList. void DrawStringInt(const base::string16& text, - const gfx::Font& font, + const Font& font, SkColor color, - int x, int y, int w, int h); + int x, + int y, + int w, + int h); void DrawStringInt(const base::string16& text, - const gfx::Font& font, + const Font& font, SkColor color, - const gfx::Rect& display_rect); + const Rect& display_rect); - // Draws text with the specified color, font and location. The last argument + // Draws text with the specified color, fonts and location. The last argument // specifies flags for how the text should be rendered. It can be one of // TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT or TEXT_ALIGN_LEFT. + void DrawStringRectWithFlags(const base::string16& text, + const FontList& font_list, + SkColor color, + const Rect& display_rect, + int flags); + // Obsolete version. Use the above version which takes FontList. void DrawStringInt(const base::string16& text, - const gfx::Font& font, + const Font& font, SkColor color, - int x, int y, int w, int h, + int x, + int y, + int w, + int h, int flags); // Similar to above DrawStringInt method but with text shadows support. // Currently it's only implemented for canvas skia. Specifying a 0 line_height // will cause the default height to be used. + void DrawStringRectWithShadows(const base::string16& text, + const FontList& font_list, + SkColor color, + const Rect& text_bounds, + int line_height, + int flags, + const ShadowValues& shadows); + // Obsolete version. Use the above version which takes FontList. void DrawStringWithShadows(const base::string16& text, - const gfx::Font& font, + const Font& font, SkColor color, - const gfx::Rect& text_bounds, + const Rect& text_bounds, int line_height, int flags, const ShadowValues& shadows); // Draws a dotted gray rectangle used for focus purposes. - void DrawFocusRect(const gfx::Rect& rect); + void DrawFocusRect(const Rect& rect); // Tiles the image in the specified region. // Parameters are specified relative to current canvas scale not in pixels. // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1. - void TileImageInt(const gfx::ImageSkia& image, - int x, int y, int w, int h); - void TileImageInt(const gfx::ImageSkia& image, - int src_x, int src_y, - int dest_x, int dest_y, int w, int h); - void TileImageInt(const gfx::ImageSkia& image, - int src_x, int src_y, - float tile_scale_x, float tile_scale_y, - int dest_x, int dest_y, int w, int h); + void TileImageInt(const ImageSkia& image, + int x, + int y, + int w, + int h); + void TileImageInt(const ImageSkia& image, + int src_x, + int src_y, + int dest_x, + int dest_y, + int w, + int h); + void TileImageInt(const ImageSkia& image, + int src_x, + int src_y, + float tile_scale_x, + float tile_scale_y, + int dest_x, + int dest_y, + int w, + int h); // Returns a native drawing context for platform specific drawing routines to // use. Must be balanced by a call to EndPlatformPaint(). @@ -359,19 +427,27 @@ class UI_EXPORT Canvas { void EndPlatformPaint(); // Apply transformation on the canvas. - void Transform(const gfx::Transform& transform); + void Transform(const Transform& transform); // Draws the given string with the beginning and/or the end using a fade // gradient. When truncating the head // |desired_characters_to_truncate_from_head| specifies the maximum number of // characters that can be truncated. + void DrawFadeTruncatingStringRect( + const base::string16& text, + TruncateFadeMode truncate_mode, + size_t desired_characters_to_truncate_from_head, + const FontList& font_list, + SkColor color, + const Rect& display_rect); + // Obsolete version. Use the above version which takes FontList. void DrawFadeTruncatingString( const base::string16& text, TruncateFadeMode truncate_mode, size_t desired_characters_to_truncate_from_head, - const gfx::Font& font, + const Font& font, SkColor color, - const gfx::Rect& display_rect); + const Rect& display_rect); skia::PlatformCanvas* platform_canvas() const { return owned_canvas_.get(); } SkCanvas* sk_canvas() const { return canvas_; } @@ -382,19 +458,18 @@ class UI_EXPORT Canvas { // Test whether the provided rectangle intersects the current clip rect. bool IntersectsClipRectInt(int x, int y, int w, int h); - bool IntersectsClipRect(const gfx::Rect& rect); + bool IntersectsClipRect(const Rect& rect); // Returns the image rep which best matches the canvas |scale_factor_|. // Returns a null image rep if |image| contains no image reps. // Builds mip map for returned image rep if necessary. // // An optional additional user defined scale can be provided. - const gfx::ImageSkiaRep& GetImageRepToPaint( - const gfx::ImageSkia& image) const; - const gfx::ImageSkiaRep& GetImageRepToPaint( - const gfx::ImageSkia& image, + const ImageSkiaRep& GetImageRepToPaint(const ImageSkia& image) const; + const ImageSkiaRep& GetImageRepToPaint( + const ImageSkia& image, float user_defined_scale_factor_x, - float user_defined_scale_factor_y) const; + float user_defined_scale_factor_y) const; // The device scale factor at which drawing on this canvas occurs. // An additional scale can be applied via Canvas::Scale(). However, diff --git a/chromium/ui/gfx/canvas_android.cc b/chromium/ui/gfx/canvas_android.cc index c26a668f1d4..54e45f7653a 100644 --- a/chromium/ui/gfx/canvas_android.cc +++ b/chromium/ui/gfx/canvas_android.cc @@ -5,13 +5,12 @@ #include "ui/gfx/canvas.h" #include "base/logging.h" -#include "ui/gfx/font.h" namespace gfx { // static void Canvas::SizeStringInt(const base::string16& text, - const gfx::Font& font, + const FontList& font_list, int* width, int* height, int line_height, @@ -19,13 +18,22 @@ void Canvas::SizeStringInt(const base::string16& text, NOTIMPLEMENTED(); } -void Canvas::DrawStringWithShadows(const base::string16& text, - const gfx::Font& font, - SkColor color, - const gfx::Rect& text_bounds, - int line_height, - int flags, - const ShadowValues& shadows) { +void Canvas::DrawStringRectWithHalo(const base::string16& text, + const FontList& font_list, + SkColor text_color, + SkColor halo_color_in, + const Rect& display_rect, + int flags) { + NOTIMPLEMENTED(); +} + +void Canvas::DrawStringRectWithShadows(const base::string16& text, + const FontList& font_list, + SkColor color, + const Rect& text_bounds, + int line_height, + int flags, + const ShadowValues& shadows) { NOTIMPLEMENTED(); } diff --git a/chromium/ui/gfx/canvas_mac.mm b/chromium/ui/gfx/canvas_mac.mm deleted file mode 100644 index a906873d4e5..00000000000 --- a/chromium/ui/gfx/canvas_mac.mm +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) 2012 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. - -#import <Cocoa/Cocoa.h> - -#include "ui/gfx/canvas.h" - -#include "base/logging.h" -#include "base/strings/sys_string_conversions.h" -#include "third_party/skia/include/core/SkTypeface.h" -#include "ui/gfx/font.h" -#include "ui/gfx/rect.h" - -// Note: This is a temporary Skia-based implementation of the ui/gfx text -// rendering routines for views/aura. It replaces the stale Cocoa-based -// implementation. A future |canvas_skia.cc| implementation will supersede -// this and the other platform-specific implmenentations. Most drawing options, -// such as alignment, multi-line, and line heights are not implemented here. - -namespace { - -SkTypeface::Style FontTypefaceStyle(const gfx::Font& font) { - int style = 0; - if (font.GetStyle() & gfx::Font::BOLD) - style |= SkTypeface::kBold; - if (font.GetStyle() & gfx::Font::ITALIC) - style |= SkTypeface::kItalic; - - return static_cast<SkTypeface::Style>(style); -} - -} // namespace - -namespace gfx { - -// static -void Canvas::SizeStringInt(const base::string16& text, - const gfx::Font& font, - int* width, - int* height, - int line_height, - int flags) { - DLOG_IF(WARNING, line_height != 0) << "Line heights not implemented."; - DLOG_IF(WARNING, flags & Canvas::MULTI_LINE) << "Multi-line not implemented."; - - NSFont* native_font = font.GetNativeFont(); - NSString* ns_string = base::SysUTF16ToNSString(text); - NSDictionary* attributes = - [NSDictionary dictionaryWithObject:native_font - forKey:NSFontAttributeName]; - NSSize string_size = [ns_string sizeWithAttributes:attributes]; - *width = string_size.width; - *height = font.GetHeight(); -} - -void Canvas::DrawStringWithShadows(const base::string16& text, - const gfx::Font& font, - SkColor color, - const gfx::Rect& text_bounds, - int line_height, - int flags, - const ShadowValues& shadows) { - DLOG_IF(WARNING, line_height != 0) << "Line heights not implemented."; - DLOG_IF(WARNING, flags & Canvas::MULTI_LINE) << "Multi-line not implemented."; - DLOG_IF(WARNING, !shadows.empty()) << "Text shadows not implemented."; - - skia::RefPtr<SkTypeface> typeface = skia::AdoptRef( - SkTypeface::CreateFromName( - font.GetFontName().c_str(), FontTypefaceStyle(font))); - SkPaint paint; - paint.setTypeface(typeface.get()); - paint.setColor(color); - canvas_->drawText(text.c_str(), - text.size() * sizeof(base::string16::value_type), - text_bounds.x(), - text_bounds.bottom(), - paint); -} - -void Canvas::DrawStringWithHalo(const base::string16& text, - const gfx::Font& font, - SkColor text_color, - SkColor halo_color, - int x, int y, int w, int h, - int flags) { -} - -} // namespace gfx diff --git a/chromium/ui/gfx/canvas_paint.h b/chromium/ui/gfx/canvas_paint.h index 1db5341adae..4ae8b7c0229 100644 --- a/chromium/ui/gfx/canvas_paint.h +++ b/chromium/ui/gfx/canvas_paint.h @@ -5,7 +5,7 @@ #ifndef UI_GFX_CANVAS_PAINT_H_ #define UI_GFX_CANVAS_PAINT_H_ -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/native_widget_types.h" namespace gfx { diff --git a/chromium/ui/gfx/canvas_paint_win.cc b/chromium/ui/gfx/canvas_paint_win.cc index 661b2976fd7..71c836724a2 100644 --- a/chromium/ui/gfx/canvas_paint_win.cc +++ b/chromium/ui/gfx/canvas_paint_win.cc @@ -56,7 +56,7 @@ void CanvasSkiaPaint::Init(bool opaque) { const int height = ps_.rcPaint.bottom - ps_.rcPaint.top; RecreateBackingCanvas(gfx::Size(width, height), - ui::GetScaleFactorFromScale(ui::win::GetDeviceScaleFactor()), + ui::GetScaleFactorFromScale(gfx::win::GetDeviceScaleFactor()), opaque); skia::PlatformCanvas* canvas = platform_canvas(); @@ -65,8 +65,8 @@ void CanvasSkiaPaint::Init(bool opaque) { // This will bring the canvas into the screen coordinate system for the // dirty rect canvas->translate( - -ps_.rcPaint.left / ui::win::GetDeviceScaleFactor(), - -ps_.rcPaint.top / ui::win::GetDeviceScaleFactor()); + -ps_.rcPaint.left / gfx::win::GetDeviceScaleFactor(), + -ps_.rcPaint.top / gfx::win::GetDeviceScaleFactor()); } } // namespace gfx diff --git a/chromium/ui/gfx/canvas_paint_win.h b/chromium/ui/gfx/canvas_paint_win.h index d9326e30c07..c5d3aee3211 100644 --- a/chromium/ui/gfx/canvas_paint_win.h +++ b/chromium/ui/gfx/canvas_paint_win.h @@ -6,9 +6,9 @@ #define UI_GFX_CANVAS_PAINT_WIN_H_ #include "skia/ext/platform_canvas.h" -#include "ui/base/win/dpi.h" #include "ui/gfx/canvas.h" #include "ui/gfx/size.h" +#include "ui/gfx/win/dpi.h" namespace gfx { diff --git a/chromium/ui/gfx/canvas_skia.cc b/chromium/ui/gfx/canvas_skia.cc index bb8ce7db5e5..ef8ee3625a7 100644 --- a/chromium/ui/gfx/canvas_skia.cc +++ b/chromium/ui/gfx/canvas_skia.cc @@ -7,14 +7,13 @@ #include "base/i18n/rtl.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" -#include "ui/base/range/range.h" -#include "ui/base/text/text_elider.h" -#include "ui/gfx/font.h" #include "ui/gfx/font_list.h" #include "ui/gfx/insets.h" +#include "ui/gfx/range/range.h" #include "ui/gfx/rect.h" #include "ui/gfx/render_text.h" #include "ui/gfx/shadow_value.h" +#include "ui/gfx/text_elider.h" #include "ui/gfx/text_utils.h" namespace gfx { @@ -57,9 +56,9 @@ bool AdjustStringDirection(int flags, base::string16* text) { // Checks each pixel immediately adjacent to the given pixel in the bitmap. If // any of them are not the halo color, returns true. This defines the halo of // pixels that will appear around the text. Note that we have to check each -// pixel against both the halo color and transparent since |DrawStringWithHalo| -// will modify the bitmap as it goes, and cleared pixels shouldn't count as -// changed. +// pixel against both the halo color and transparent since +// |DrawStringRectWithHalo| will modify the bitmap as it goes, and cleared +// pixels shouldn't count as changed. bool PixelShouldGetHalo(const SkBitmap& bitmap, int x, int y, SkColor halo_color) { @@ -83,49 +82,49 @@ bool PixelShouldGetHalo(const SkBitmap& bitmap, } // Strips accelerator character prefixes in |text| if needed, based on |flags|. -// Returns a range in |text| to underline or ui::Range::InvalidRange() if +// Returns a range in |text| to underline or gfx::Range::InvalidRange() if // underlining is not needed. -ui::Range StripAcceleratorChars(int flags, base::string16* text) { +Range StripAcceleratorChars(int flags, base::string16* text) { if (flags & (Canvas::SHOW_PREFIX | Canvas::HIDE_PREFIX)) { int char_pos = -1; int char_span = 0; *text = RemoveAcceleratorChar(*text, '&', &char_pos, &char_span); if ((flags & Canvas::SHOW_PREFIX) && char_pos != -1) - return ui::Range(char_pos, char_pos + char_span); + return Range(char_pos, char_pos + char_span); } - return ui::Range::InvalidRange(); + return Range::InvalidRange(); } // Elides |text| and adjusts |range| appropriately. If eliding causes |range| // to no longer point to the same character in |text|, |range| is made invalid. -void ElideTextAndAdjustRange(const Font& font, +void ElideTextAndAdjustRange(const FontList& font_list, int width, base::string16* text, - ui::Range* range) { + Range* range) { const base::char16 start_char = (range->IsValid() ? text->at(range->start()) : 0); - *text = ui::ElideText(*text, font, width, ui::ELIDE_AT_END); + *text = gfx::ElideText(*text, font_list, width, gfx::ELIDE_AT_END); if (!range->IsValid()) return; if (range->start() >= text->length() || text->at(range->start()) != start_char) { - *range = ui::Range::InvalidRange(); + *range = Range::InvalidRange(); } } // Updates |render_text| from the specified parameters. void UpdateRenderText(const Rect& rect, const base::string16& text, - const Font& font, + const FontList& font_list, int flags, SkColor color, RenderText* render_text) { - render_text->SetFont(font); + render_text->SetFontList(font_list); render_text->SetText(text); render_text->SetCursorEnabled(false); Rect display_rect = rect; - display_rect.set_height(font.GetHeight()); + display_rect.set_height(font_list.GetHeight()); render_text->SetDisplayRect(display_rect); // Set the text alignment explicitly based on the directionality of the UI, @@ -147,9 +146,10 @@ void UpdateRenderText(const Rect& rect, render_text->set_background_is_transparent(true); render_text->SetColor(color); - render_text->SetStyle(BOLD, (font.GetStyle() & Font::BOLD) != 0); - render_text->SetStyle(ITALIC, (font.GetStyle() & Font::ITALIC) != 0); - render_text->SetStyle(UNDERLINE, (font.GetStyle() & Font::UNDERLINE) != 0); + const int font_style = font_list.GetFontStyle(); + render_text->SetStyle(BOLD, (font_style & Font::BOLD) != 0); + render_text->SetStyle(ITALIC, (font_style & Font::ITALIC) != 0); + render_text->SetStyle(UNDERLINE, (font_style & Font::UNDERLINE) != 0); } // Returns updated |flags| to match platform-specific expected behavior. @@ -168,7 +168,7 @@ int AdjustPlatformSpecificFlags(const base::string16& text, int flags) { // static void Canvas::SizeStringInt(const base::string16& text, - const Font& font, + const FontList& font_list, int* width, int* height, int line_height, int flags) { @@ -183,25 +183,27 @@ void Canvas::SizeStringInt(const base::string16& text, #endif if ((flags & MULTI_LINE) && *width != 0) { - ui::WordWrapBehavior wrap_behavior = ui::TRUNCATE_LONG_WORDS; + gfx::WordWrapBehavior wrap_behavior = gfx::TRUNCATE_LONG_WORDS; if (flags & CHARACTER_BREAK) - wrap_behavior = ui::WRAP_LONG_WORDS; + wrap_behavior = gfx::WRAP_LONG_WORDS; else if (!(flags & NO_ELLIPSIS)) - wrap_behavior = ui::ELIDE_LONG_WORDS; + wrap_behavior = gfx::ELIDE_LONG_WORDS; Rect rect(*width, INT_MAX); std::vector<base::string16> strings; - ui::ElideRectangleText(adjusted_text, font, rect.width(), rect.height(), + gfx::ElideRectangleText(adjusted_text, font_list, + rect.width(), rect.height(), wrap_behavior, &strings); scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); - UpdateRenderText(rect, base::string16(), font, flags, 0, render_text.get()); + UpdateRenderText(rect, base::string16(), font_list, flags, 0, + render_text.get()); int h = 0; int w = 0; for (size_t i = 0; i < strings.size(); ++i) { StripAcceleratorChars(flags, &strings[i]); render_text->SetText(strings[i]); - const Size string_size = render_text->GetStringSize(); + const Size& string_size = render_text->GetStringSize(); w = std::max(w, string_size.width()); h += (i > 0 && line_height > 0) ? line_height : string_size.height(); } @@ -212,27 +214,28 @@ void Canvas::SizeStringInt(const base::string16& text, // will inexplicably fail with result E_INVALIDARG. Guard against this. const size_t kMaxRenderTextLength = 5000; if (adjusted_text.length() >= kMaxRenderTextLength) { - *width = adjusted_text.length() * font.GetAverageCharacterWidth(); - *height = font.GetHeight(); + *width = font_list.GetExpectedTextWidth(adjusted_text.length()); + *height = font_list.GetHeight(); } else { scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); Rect rect(*width, *height); StripAcceleratorChars(flags, &adjusted_text); - UpdateRenderText(rect, adjusted_text, font, flags, 0, render_text.get()); - const Size string_size = render_text->GetStringSize(); + UpdateRenderText(rect, adjusted_text, font_list, flags, 0, + render_text.get()); + const Size& string_size = render_text->GetStringSize(); *width = string_size.width(); *height = string_size.height(); } } } -void Canvas::DrawStringWithShadows(const base::string16& text, - const Font& font, - SkColor color, - const Rect& text_bounds, - int line_height, - int flags, - const ShadowValues& shadows) { +void Canvas::DrawStringRectWithShadows(const base::string16& text, + const FontList& font_list, + SkColor color, + const Rect& text_bounds, + int line_height, + int flags, + const ShadowValues& shadows) { if (!IntersectsClipRect(text_bounds)) return; @@ -255,22 +258,23 @@ void Canvas::DrawStringWithShadows(const base::string16& text, render_text->SetTextShadows(shadows); if (flags & MULTI_LINE) { - ui::WordWrapBehavior wrap_behavior = ui::IGNORE_LONG_WORDS; + gfx::WordWrapBehavior wrap_behavior = gfx::IGNORE_LONG_WORDS; if (flags & CHARACTER_BREAK) - wrap_behavior = ui::WRAP_LONG_WORDS; + wrap_behavior = gfx::WRAP_LONG_WORDS; else if (!(flags & NO_ELLIPSIS)) - wrap_behavior = ui::ELIDE_LONG_WORDS; + wrap_behavior = gfx::ELIDE_LONG_WORDS; std::vector<base::string16> strings; - ui::ElideRectangleText(adjusted_text, - font, + gfx::ElideRectangleText(adjusted_text, + font_list, text_bounds.width(), text_bounds.height(), wrap_behavior, &strings); for (size_t i = 0; i < strings.size(); i++) { - ui::Range range = StripAcceleratorChars(flags, &strings[i]); - UpdateRenderText(rect, strings[i], font, flags, color, render_text.get()); + Range range = StripAcceleratorChars(flags, &strings[i]); + UpdateRenderText(rect, strings[i], font_list, flags, color, + render_text.get()); int line_padding = 0; if (line_height > 0) line_padding = line_height - render_text->GetStringSize().height(); @@ -295,7 +299,7 @@ void Canvas::DrawStringWithShadows(const base::string16& text, rect += Vector2d(0, line_height); } } else { - ui::Range range = StripAcceleratorChars(flags, &adjusted_text); + Range range = StripAcceleratorChars(flags, &adjusted_text); bool elide_text = ((flags & NO_ELLIPSIS) == 0); #if defined(OS_LINUX) @@ -311,13 +315,13 @@ void Canvas::DrawStringWithShadows(const base::string16& text, #endif if (elide_text) { - ElideTextAndAdjustRange(font, + ElideTextAndAdjustRange(font_list, text_bounds.width(), &adjusted_text, &range); } - UpdateRenderText(rect, adjusted_text, font, flags, color, + UpdateRenderText(rect, adjusted_text, font_list, flags, color, render_text.get()); const int text_height = render_text->GetStringSize().height(); @@ -333,19 +337,19 @@ void Canvas::DrawStringWithShadows(const base::string16& text, canvas_->restore(); } -void Canvas::DrawStringWithHalo(const base::string16& text, - const Font& font, - SkColor text_color, - SkColor halo_color_in, - int x, int y, int w, int h, - int flags) { +void Canvas::DrawStringRectWithHalo(const base::string16& text, + const FontList& font_list, + SkColor text_color, + SkColor halo_color_in, + const Rect& display_rect, + int flags) { // Some callers will have semitransparent halo colors, which we don't handle // (since the resulting image can have 1-bit transparency only). SkColor halo_color = SkColorSetA(halo_color_in, 0xFF); // Create a temporary buffer filled with the halo color. It must leave room // for the 1-pixel border around the text. - Size size(w + 2, h + 2); + Size size(display_rect.width() + 2, display_rect.height() + 2); Canvas text_canvas(size, scale_factor(), true); SkPaint bkgnd_paint; bkgnd_paint.setColor(halo_color); @@ -353,7 +357,9 @@ void Canvas::DrawStringWithHalo(const base::string16& text, // Draw the text into the temporary buffer. This will have correct // ClearType since the background color is the same as the halo color. - text_canvas.DrawStringInt(text, font, text_color, 1, 1, w, h, flags); + text_canvas.DrawStringRectWithFlags( + text, font_list, text_color, + Rect(1, 1, display_rect.width(), display_rect.height()), flags); uint32_t halo_premul = SkPreMultiplyColor(halo_color); SkBitmap& text_bitmap = const_cast<SkBitmap&>( @@ -376,22 +382,21 @@ void Canvas::DrawStringWithHalo(const base::string16& text, // Draw the halo bitmap with blur. ImageSkia text_image = ImageSkia(ImageSkiaRep(text_bitmap, text_canvas.scale_factor())); - DrawImageInt(text_image, x - 1, y - 1); + DrawImageInt(text_image, display_rect.x() - 1, display_rect.y() - 1); } -void Canvas::DrawFadeTruncatingString( - const base::string16& text, - TruncateFadeMode truncate_mode, - size_t desired_characters_to_truncate_from_head, - const Font& font, - SkColor color, - const Rect& display_rect) { +void Canvas::DrawFadeTruncatingStringRect( + const base::string16& text, + TruncateFadeMode truncate_mode, + size_t desired_characters_to_truncate_from_head, + const FontList& font_list, + SkColor color, + const Rect& display_rect) { int flags = NO_ELLIPSIS; // If the whole string fits in the destination then just draw it directly. - if (GetStringWidth(text, font) <= display_rect.width()) { - DrawStringInt(text, font, color, display_rect.x(), display_rect.y(), - display_rect.width(), display_rect.height(), flags); + if (GetStringWidth(text, font_list) <= display_rect.width()) { + DrawStringRectWithFlags(text, font_list, color, display_rect, flags); return; } @@ -437,7 +442,8 @@ void Canvas::DrawFadeTruncatingString( flags |= TEXT_ALIGN_LEFT; Rect rect = display_rect; - UpdateRenderText(rect, clipped_text, font, flags, color, render_text.get()); + UpdateRenderText(rect, clipped_text, font_list, flags, color, + render_text.get()); const int line_height = render_text->GetStringSize().height(); // Center the text vertically. @@ -451,4 +457,16 @@ void Canvas::DrawFadeTruncatingString( canvas_->restore(); } +void Canvas::DrawFadeTruncatingString( + const base::string16& text, + TruncateFadeMode truncate_mode, + size_t desired_characters_to_truncate_from_head, + const Font& font, + SkColor color, + const Rect& display_rect) { + DrawFadeTruncatingStringRect(text, truncate_mode, + desired_characters_to_truncate_from_head, + FontList(font), color, display_rect); +} + } // namespace gfx diff --git a/chromium/ui/gfx/canvas_unittest_mac.mm b/chromium/ui/gfx/canvas_unittest_mac.mm new file mode 100644 index 00000000000..d607218c64f --- /dev/null +++ b/chromium/ui/gfx/canvas_unittest_mac.mm @@ -0,0 +1,84 @@ +// 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 "ui/gfx/canvas.h" + +#include <cmath> + +#import <Cocoa/Cocoa.h> + +#include "base/strings/utf_string_conversions.h" +#include "base/strings/sys_string_conversions.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/font.h" +#include "ui/gfx/font_list.h" + +namespace gfx { + +namespace { + +// Mac-specific code for string size computations. This is a verbatim copy +// of the old implementation that used to be in canvas_mac.mm. +void CanvasMac_SizeStringInt(const base::string16& text, + const FontList& font_list, + int* width, + int* height, + int line_height, + int flags) { + DLOG_IF(WARNING, line_height != 0) << "Line heights not implemented."; + DLOG_IF(WARNING, flags & Canvas::MULTI_LINE) << "Multi-line not implemented."; + + NSFont* native_font = font_list.GetPrimaryFont().GetNativeFont(); + NSString* ns_string = base::SysUTF16ToNSString(text); + NSDictionary* attributes = + [NSDictionary dictionaryWithObject:native_font + forKey:NSFontAttributeName]; + NSSize string_size = [ns_string sizeWithAttributes:attributes]; + *width = std::ceil(string_size.width); + *height = font_list.GetHeight(); +} + +} // namespace + +class CanvasTestMac : public testing::Test { + protected: + // Compare the size returned by Canvas::SizeStringInt to the size generated + // by the platform-specific version in CanvasMac_SizeStringInt. Will generate + // expectation failure on any mismatch. Only works for single-line text + // without specified line height, since that is all the platform + // implementation supports. + void CompareSizes(const char* text) { + const int kReallyLargeNumber = 12345678; + FontList font_list(font_); + base::string16 text16 = base::UTF8ToUTF16(text); + + int mac_width = kReallyLargeNumber; + int mac_height = kReallyLargeNumber; + CanvasMac_SizeStringInt(text16, font_list, &mac_width, &mac_height, 0, 0); + + int canvas_width = kReallyLargeNumber; + int canvas_height = kReallyLargeNumber; + Canvas::SizeStringInt( + text16, font_list, &canvas_width, &canvas_height, 0, 0); + + EXPECT_NE(kReallyLargeNumber, mac_width) << "no width for " << text; + EXPECT_NE(kReallyLargeNumber, mac_height) << "no height for " << text; + EXPECT_EQ(mac_width, canvas_width) << " width for " << text; + EXPECT_EQ(mac_height, canvas_height) << " height for " << text; + } + + private: + Font font_; +}; + + // Tests that Canvas' SizeStringInt yields result consistent with a native + // implementation. + TEST_F(CanvasTestMac, StringSizeIdenticalForSkia) { + CompareSizes(""); + CompareSizes("Foo"); + CompareSizes("Longword"); + CompareSizes("This is a complete sentence."); +} + +} // namespace gfx diff --git a/chromium/ui/gfx/codec/OWNERS b/chromium/ui/gfx/codec/OWNERS new file mode 100644 index 00000000000..44aa7e470f9 --- /dev/null +++ b/chromium/ui/gfx/codec/OWNERS @@ -0,0 +1,2 @@ +erg@chromium.org +dcheng@chromium.org diff --git a/chromium/ui/gfx/codec/jpeg_codec.h b/chromium/ui/gfx/codec/jpeg_codec.h index e4edeee2236..b6b7088c361 100644 --- a/chromium/ui/gfx/codec/jpeg_codec.h +++ b/chromium/ui/gfx/codec/jpeg_codec.h @@ -8,7 +8,7 @@ #include <stddef.h> #include <vector> -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" class SkBitmap; diff --git a/chromium/ui/gfx/codec/png_codec.cc b/chromium/ui/gfx/codec/png_codec.cc index 360526b3436..30e4eb6d653 100644 --- a/chromium/ui/gfx/codec/png_codec.cc +++ b/chromium/ui/gfx/codec/png_codec.cc @@ -472,7 +472,7 @@ bool PNGCodec::Decode(const unsigned char* input, size_t input_size, // static SkBitmap* PNGCodec::CreateSkBitmapFromBGRAFormat( - std::vector<unsigned char>& bgra, int width, int height) { + const std::vector<unsigned char>& bgra, int width, int height) { SkBitmap* bitmap = new SkBitmap(); bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height); bitmap->allocPixels(); @@ -654,29 +654,14 @@ bool DoLibpngWrite(png_struct* png_ptr, png_info* info_ptr, return true; } -} // namespace - -// static -bool PNGCodec::Encode(const unsigned char* input, ColorFormat format, - const Size& size, int row_byte_width, - bool discard_transparency, - const std::vector<Comment>& comments, - std::vector<unsigned char>* output) { - return PNGCodec::EncodeWithCompressionLevel(input, format, size, - row_byte_width, - discard_transparency, - comments, Z_DEFAULT_COMPRESSION, - output); -} - -// static -bool PNGCodec::EncodeWithCompressionLevel(const unsigned char* input, - ColorFormat format, const Size& size, - int row_byte_width, - bool discard_transparency, - const std::vector<Comment>& comments, - int compression_level, - std::vector<unsigned char>* output) { +bool EncodeWithCompressionLevel(const unsigned char* input, + PNGCodec::ColorFormat format, + const Size& size, + int row_byte_width, + bool discard_transparency, + const std::vector<PNGCodec::Comment>& comments, + int compression_level, + std::vector<unsigned char>* output) { // Run to convert an input row into the output row format, NULL means no // conversion is necessary. FormatConverter converter = NULL; @@ -684,13 +669,13 @@ bool PNGCodec::EncodeWithCompressionLevel(const unsigned char* input, int input_color_components, output_color_components; int png_output_color_type; switch (format) { - case FORMAT_RGB: + case PNGCodec::FORMAT_RGB: input_color_components = 3; output_color_components = 3; png_output_color_type = PNG_COLOR_TYPE_RGB; break; - case FORMAT_RGBA: + case PNGCodec::FORMAT_RGBA: input_color_components = 4; if (discard_transparency) { output_color_components = 3; @@ -703,7 +688,7 @@ bool PNGCodec::EncodeWithCompressionLevel(const unsigned char* input, } break; - case FORMAT_BGRA: + case PNGCodec::FORMAT_BGRA: input_color_components = 4; if (discard_transparency) { output_color_components = 3; @@ -716,7 +701,7 @@ bool PNGCodec::EncodeWithCompressionLevel(const unsigned char* input, } break; - case FORMAT_SkBitmap: + case PNGCodec::FORMAT_SkBitmap: input_color_components = 4; if (discard_transparency) { output_color_components = 3; @@ -758,24 +743,62 @@ bool PNGCodec::EncodeWithCompressionLevel(const unsigned char* input, return success; } + +} // namespace + +// static +bool PNGCodec::Encode(const unsigned char* input, ColorFormat format, + const Size& size, int row_byte_width, + bool discard_transparency, + const std::vector<Comment>& comments, + std::vector<unsigned char>* output) { + return EncodeWithCompressionLevel(input, + format, + size, + row_byte_width, + discard_transparency, + comments, + Z_DEFAULT_COMPRESSION, + output); +} + // static bool PNGCodec::EncodeBGRASkBitmap(const SkBitmap& input, bool discard_transparency, std::vector<unsigned char>* output) { static const int bbp = 4; - SkAutoLockPixels lock_input(input); if (input.empty()) return false; - DCHECK(input.bytesPerPixel() == bbp); - DCHECK(static_cast<int>(input.rowBytes()) >= input.width() * bbp); + DCHECK_EQ(input.bytesPerPixel(), bbp); + DCHECK_GE(static_cast<int>(input.rowBytes()), input.width() * bbp); + SkAutoLockPixels lock_input(input); return Encode(reinterpret_cast<unsigned char*>(input.getAddr32(0, 0)), FORMAT_SkBitmap, Size(input.width(), input.height()), static_cast<int>(input.rowBytes()), discard_transparency, std::vector<Comment>(), output); } +// static +bool PNGCodec::FastEncodeBGRASkBitmap(const SkBitmap& input, + bool discard_transparency, + std::vector<unsigned char>* output) { + static const int bbp = 4; + + if (input.empty()) + return false; + DCHECK_EQ(input.bytesPerPixel(), bbp); + DCHECK_GE(static_cast<int>(input.rowBytes()), input.width() * bbp); + + SkAutoLockPixels lock_input(input); + return EncodeWithCompressionLevel( + reinterpret_cast<unsigned char*>(input.getAddr32(0, 0)), + FORMAT_SkBitmap, Size(input.width(), input.height()), + static_cast<int>(input.rowBytes()), discard_transparency, + std::vector<Comment>(), Z_BEST_SPEED, output); +} + PNGCodec::Comment::Comment(const std::string& k, const std::string& t) : key(k), text(t) { } diff --git a/chromium/ui/gfx/codec/png_codec.h b/chromium/ui/gfx/codec/png_codec.h index 3a6d295dbdf..86f170d359f 100644 --- a/chromium/ui/gfx/codec/png_codec.h +++ b/chromium/ui/gfx/codec/png_codec.h @@ -9,7 +9,7 @@ #include <vector> #include "base/basictypes.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" class SkBitmap; @@ -51,16 +51,6 @@ class UI_EXPORT PNGCodec { std::string text; }; - // Calls PNGCodec::EncodeWithCompressionLevel with the default compression - // level. - static bool Encode(const unsigned char* input, - ColorFormat format, - const Size& size, - int row_byte_width, - bool discard_transparency, - const std::vector<Comment>& comments, - std::vector<unsigned char>* output); - // Encodes the given raw 'input' data, with each pixel being represented as // given in 'format'. The encoded PNG data will be written into the supplied // vector and true will be returned on success. On failure (false), the @@ -78,16 +68,13 @@ class UI_EXPORT PNGCodec { // written to the resulting file. Otherwise, alpha values in the input // will be preserved. // comments: comments to be written in the png's metadata. - // compression_level: An integer between -1 and 9, corresponding to zlib's - // compression levels. -1 is the default. - static bool EncodeWithCompressionLevel(const unsigned char* input, - ColorFormat format, - const Size& size, - int row_byte_width, - bool discard_transparency, - const std::vector<Comment>& comments, - int compression_level, - std::vector<unsigned char>* output); + static bool Encode(const unsigned char* input, + ColorFormat format, + const Size& size, + int row_byte_width, + bool discard_transparency, + const std::vector<Comment>& comments, + std::vector<unsigned char>* output); // Call PNGCodec::Encode on the supplied SkBitmap |input|, which is assumed // to be BGRA, 32 bits per pixel. The params |discard_transparency| and @@ -97,6 +84,13 @@ class UI_EXPORT PNGCodec { bool discard_transparency, std::vector<unsigned char>* output); + // Call PNGCodec::Encode on the supplied SkBitmap |input|. The difference + // between this and the previous method is that this restricts compression to + // zlib q1, which is just rle encoding. + static bool FastEncodeBGRASkBitmap(const SkBitmap& input, + bool discard_transparency, + std::vector<unsigned char>* output); + // Decodes the PNG data contained in input of length input_size. The // decoded data will be placed in *output with the dimensions in *w and *h // on success (returns true). This data will be written in the 'format' @@ -123,7 +117,7 @@ class UI_EXPORT PNGCodec { // Create a SkBitmap from a decoded BGRA DIB. The caller owns the returned // SkBitmap. static SkBitmap* CreateSkBitmapFromBGRAFormat( - std::vector<unsigned char>& bgra, int width, int height); + const std::vector<unsigned char>& bgra, int width, int height); private: DISALLOW_COPY_AND_ASSIGN(PNGCodec); diff --git a/chromium/ui/gfx/codec/png_codec_unittest.cc b/chromium/ui/gfx/codec/png_codec_unittest.cc index e3540a27114..f1654d9d363 100644 --- a/chromium/ui/gfx/codec/png_codec_unittest.cc +++ b/chromium/ui/gfx/codec/png_codec_unittest.cc @@ -14,6 +14,7 @@ #include "third_party/zlib/zlib.h" #include "ui/gfx/codec/png_codec.h" #include "ui/gfx/size.h" +#include "ui/gfx/skia_util.h" namespace gfx { @@ -1119,43 +1120,31 @@ TEST(PNGCodec, EncodeDecodeWithVaryingCompressionLevels) { // create an image with known values, a must be opaque because it will be // lost during encoding - std::vector<unsigned char> original; - MakeRGBAImage(w, h, true, &original); + SkBitmap original_bitmap; + MakeTestSkBitmap(w, h, &original_bitmap); // encode - std::vector<unsigned char> encoded_fast; - EXPECT_TRUE(PNGCodec::EncodeWithCompressionLevel( - &original[0], PNGCodec::FORMAT_RGBA, Size(w, h), w * 4, false, - std::vector<PNGCodec::Comment>(), Z_BEST_SPEED, &encoded_fast)); + std::vector<unsigned char> encoded_normal; + EXPECT_TRUE( + PNGCodec::EncodeBGRASkBitmap(original_bitmap, false, &encoded_normal)); - std::vector<unsigned char> encoded_best; - EXPECT_TRUE(PNGCodec::EncodeWithCompressionLevel( - &original[0], PNGCodec::FORMAT_RGBA, Size(w, h), w * 4, false, - std::vector<PNGCodec::Comment>(), Z_BEST_COMPRESSION, &encoded_best)); + std::vector<unsigned char> encoded_fast; + EXPECT_TRUE( + PNGCodec::FastEncodeBGRASkBitmap(original_bitmap, false, &encoded_fast)); // Make sure the different compression settings actually do something; the // sizes should be different. - EXPECT_NE(encoded_fast.size(), encoded_best.size()); - - // decode, it should have the same size as the original - std::vector<unsigned char> decoded; - int outw, outh; - EXPECT_TRUE(PNGCodec::Decode(&encoded_fast[0], encoded_fast.size(), - PNGCodec::FORMAT_RGBA, &decoded, - &outw, &outh)); - ASSERT_EQ(w, outw); - ASSERT_EQ(h, outh); - ASSERT_EQ(original.size(), decoded.size()); + EXPECT_NE(encoded_normal.size(), encoded_fast.size()); - EXPECT_TRUE(PNGCodec::Decode(&encoded_best[0], encoded_best.size(), - PNGCodec::FORMAT_RGBA, &decoded, - &outw, &outh)); - ASSERT_EQ(w, outw); - ASSERT_EQ(h, outh); - ASSERT_EQ(original.size(), decoded.size()); + // decode, they should be identical to the original. + SkBitmap decoded; + EXPECT_TRUE( + PNGCodec::Decode(&encoded_normal[0], encoded_normal.size(), &decoded)); + EXPECT_TRUE(BitmapsAreEqual(decoded, original_bitmap)); - // Images must be exactly equal - ASSERT_TRUE(original == decoded); + EXPECT_TRUE( + PNGCodec::Decode(&encoded_fast[0], encoded_fast.size(), &decoded)); + EXPECT_TRUE(BitmapsAreEqual(decoded, original_bitmap)); } diff --git a/chromium/ui/gfx/color_analysis.h b/chromium/ui/gfx/color_analysis.h index 1d0b1a51409..797b4f94663 100644 --- a/chromium/ui/gfx/color_analysis.h +++ b/chromium/ui/gfx/color_analysis.h @@ -10,7 +10,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/ref_counted_memory.h" #include "third_party/skia/include/core/SkColor.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/matrix3_f.h" class SkBitmap; diff --git a/chromium/ui/gfx/color_profile.h b/chromium/ui/gfx/color_profile.h index 5e50f6b88a2..3a3f5b2ce04 100644 --- a/chromium/ui/gfx/color_profile.h +++ b/chromium/ui/gfx/color_profile.h @@ -9,7 +9,7 @@ #include "base/basictypes.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" namespace gfx { diff --git a/chromium/ui/gfx/color_profile_win.cc b/chromium/ui/gfx/color_profile_win.cc index 51b1b312d08..2e08a36d4b6 100644 --- a/chromium/ui/gfx/color_profile_win.cc +++ b/chromium/ui/gfx/color_profile_win.cc @@ -21,7 +21,7 @@ void ReadColorProfile(std::vector<char>* profile) { if (!res) return; std::string profileData; - if (!file_util::ReadFileToString(base::FilePath(path), &profileData)) + if (!base::ReadFileToString(base::FilePath(path), &profileData)) return; size_t length = profileData.size(); if (length > gfx::kMaxProfileLength) diff --git a/chromium/ui/gfx/color_utils.h b/chromium/ui/gfx/color_utils.h index c9f62066427..440e3825c31 100644 --- a/chromium/ui/gfx/color_utils.h +++ b/chromium/ui/gfx/color_utils.h @@ -7,7 +7,7 @@ #include "base/basictypes.h" #include "third_party/skia/include/core/SkColor.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" class SkBitmap; diff --git a/chromium/ui/gfx/display.cc b/chromium/ui/gfx/display.cc index 02d97a903fc..ee650d8964f 100644 --- a/chromium/ui/gfx/display.cc +++ b/chromium/ui/gfx/display.cc @@ -4,15 +4,17 @@ #include "ui/gfx/display.h" +#include <algorithm> + #include "base/command_line.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" -#include "ui/base/ui_base_switches.h" #include "ui/gfx/insets.h" #include "ui/gfx/point_conversions.h" #include "ui/gfx/point_f.h" #include "ui/gfx/size_conversions.h" +#include "ui/gfx/switches.h" namespace gfx { namespace { diff --git a/chromium/ui/gfx/display.h b/chromium/ui/gfx/display.h index 2282cb0a568..17cedfe38fe 100644 --- a/chromium/ui/gfx/display.h +++ b/chromium/ui/gfx/display.h @@ -7,11 +7,15 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/rect.h" namespace gfx { +// This class typically, but does not always, correspond to a physical display +// connected to the system. A fake Display may exist on a headless system, or a +// Display may correspond to a remote, virtual display. +// // Note: The screen and display currently uses pixel coordinate // system. For platforms that support DIP (density independent pixel), // |bounds()| and |work_area| will return values in DIP coordinate diff --git a/chromium/ui/gfx/display_observer.h b/chromium/ui/gfx/display_observer.h index 85a4086bb5a..1e7cd8cb899 100644 --- a/chromium/ui/gfx/display_observer.h +++ b/chromium/ui/gfx/display_observer.h @@ -5,7 +5,7 @@ #ifndef UI_GFX_DISPLAY_OBSERVER_H_ #define UI_GFX_DISPLAY_OBSERVER_H_ -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" namespace gfx { class Display; diff --git a/chromium/ui/gfx/favicon_size.h b/chromium/ui/gfx/favicon_size.h index 6b2c6a14f4f..ecab851dc1a 100644 --- a/chromium/ui/gfx/favicon_size.h +++ b/chromium/ui/gfx/favicon_size.h @@ -5,7 +5,7 @@ #ifndef UI_GFX_FAVICON_SIZE_H_ #define UI_GFX_FAVICON_SIZE_H_ -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" namespace gfx { diff --git a/chromium/ui/gfx/font.h b/chromium/ui/gfx/font.h index bd6e4650767..dfbf410f30c 100644 --- a/chromium/ui/gfx/font.h +++ b/chromium/ui/gfx/font.h @@ -9,7 +9,7 @@ #include "base/memory/ref_counted.h" #include "base/strings/string16.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/native_widget_types.h" namespace gfx { diff --git a/chromium/ui/gfx/font_list.h b/chromium/ui/gfx/font_list.h index 22be9121cc0..ae96251cce8 100644 --- a/chromium/ui/gfx/font_list.h +++ b/chromium/ui/gfx/font_list.h @@ -8,8 +8,8 @@ #include <string> #include <vector> -#include "ui/base/ui_export.h" #include "ui/gfx/font.h" +#include "ui/gfx/gfx_export.h" namespace gfx { diff --git a/chromium/ui/gfx/font_render_params_linux.h b/chromium/ui/gfx/font_render_params_linux.h index ec39302dccc..9ba6ca971b2 100644 --- a/chromium/ui/gfx/font_render_params_linux.h +++ b/chromium/ui/gfx/font_render_params_linux.h @@ -5,7 +5,7 @@ #ifndef UI_GFX_FONT_RENDER_PARAMS_LINUX_H_ #define UI_GFX_FONT_RENDER_PARAMS_LINUX_H_ -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" namespace gfx { diff --git a/chromium/ui/gfx/font_smoothing_win.cc b/chromium/ui/gfx/font_smoothing_win.cc index a4be72930a4..b181fb564e8 100644 --- a/chromium/ui/gfx/font_smoothing_win.cc +++ b/chromium/ui/gfx/font_smoothing_win.cc @@ -5,13 +5,13 @@ #include "ui/gfx/font_smoothing_win.h" #include "base/memory/singleton.h" -#include "ui/base/win/singleton_hwnd.h" +#include "ui/gfx/win/singleton_hwnd.h" namespace { // Helper class to cache font smoothing settings and listen for notifications // to re-query them from the system. -class CachedFontSmoothingSettings : public ui::SingletonHwnd::Observer { +class CachedFontSmoothingSettings : public gfx::SingletonHwnd::Observer { public: static CachedFontSmoothingSettings* GetInstance(); @@ -66,7 +66,7 @@ void CachedFontSmoothingSettings::GetFontSmoothingSettings( need_to_query_settings_ = false; } if (!observer_added_) { - ui::SingletonHwnd::GetInstance()->AddObserver(this); + gfx::SingletonHwnd::GetInstance()->AddObserver(this); observer_added_ = true; } *smoothing_enabled = smoothing_enabled_; diff --git a/chromium/ui/gfx/gdi_util.h b/chromium/ui/gfx/gdi_util.h index fdf6a67bf20..53b6e91a897 100644 --- a/chromium/ui/gfx/gdi_util.h +++ b/chromium/ui/gfx/gdi_util.h @@ -8,7 +8,7 @@ #include <vector> #include <windows.h> -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/rect.h" #include "ui/gfx/path.h" diff --git a/chromium/ui/base/gtk/gdk_x_compat.h b/chromium/ui/gfx/gdk_compat.h index fd395c78f6a..b11d7795831 100644 --- a/chromium/ui/base/gtk/gdk_x_compat.h +++ b/chromium/ui/gfx/gdk_compat.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_GTK_GDK_X_COMPAT_H_ -#define UI_BASE_GTK_GDK_X_COMPAT_H_ +#ifndef UI_GFX_GDK_COMPAT_H_ +#define UI_GFX_GDK_COMPAT_H_ #include <gtk/gtk.h> #include <gdk/gdkx.h> @@ -24,4 +24,4 @@ inline GdkWindow* gdk_x11_window_lookup_for_display(GdkDisplay* display, } #endif -#endif // UI_BASE_GTK_GDK_X_COMPAT_H_ +#endif // UI_GFX_GDK_COMPAT_H_ diff --git a/chromium/ui/gfx/gfx_export.h b/chromium/ui/gfx/gfx_export.h new file mode 100644 index 00000000000..f610d98d82d --- /dev/null +++ b/chromium/ui/gfx/gfx_export.h @@ -0,0 +1,33 @@ +// Copyright (c) 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. + +#ifndef UI_GFX_GFX_EXPORT_H_ +#define UI_GFX_GFX_EXPORT_H_ + +// TODO(beng): remove include once gfx dependencies have been corrected. + +#include "ui/base/ui_export.h" + +#if defined(COMPONENT_BUILD) +#if defined(WIN32) + +#if defined(UI_IMPLEMENTATION) +#define GFX_EXPORT __declspec(dllexport) +#else +#define GFX_EXPORT __declspec(dllimport) +#endif // defined(UI_IMPLEMENTATION) + +#else // defined(WIN32) +#if defined(UI_IMPLEMENTATION) +#define GFX_EXPORT __attribute__((visibility("default"))) +#else +#define GFX_EXPORT +#endif +#endif + +#else // defined(COMPONENT_BUILD) +#define GFX_EXPORT +#endif + +#endif // UI_GFX_GFX_EXPORT_H_ diff --git a/chromium/ui/gfx/gfx_paths.h b/chromium/ui/gfx/gfx_paths.h index 24fad8b4cb1..d5eec96fd74 100644 --- a/chromium/ui/gfx/gfx_paths.h +++ b/chromium/ui/gfx/gfx_paths.h @@ -5,7 +5,7 @@ #ifndef UI_GFX_GFX_PATHS_H_ #define UI_GFX_GFX_PATHS_H_ -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" // This file declares path keys for the app module. These can be used with // the PathService to access various special directories and files. diff --git a/chromium/ui/gfx/gpu_memory_buffer.h b/chromium/ui/gfx/gpu_memory_buffer.h index ff94979ff01..c600527f022 100644 --- a/chromium/ui/gfx/gpu_memory_buffer.h +++ b/chromium/ui/gfx/gpu_memory_buffer.h @@ -7,7 +7,7 @@ #include "base/memory/shared_memory.h" #include "build/build_config.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #if defined(OS_ANDROID) #include <third_party/khronos/EGL/egl.h> diff --git a/chromium/ui/base/gtk/gtk_compat.h b/chromium/ui/gfx/gtk_compat.h index 0518fad23f2..ca14a27627a 100644 --- a/chromium/ui/base/gtk/gtk_compat.h +++ b/chromium/ui/gfx/gtk_compat.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_GTK_GTK_COMPAT_H_ -#define UI_BASE_GTK_GTK_COMPAT_H_ +#ifndef UI_GFX_GTK_COMPAT_H_ +#define UI_GFX_GTK_COMPAT_H_ #include <gtk/gtk.h> @@ -94,4 +94,4 @@ inline int gdk_window_get_width(GdkWindow* window) { } #endif // !GTK_CHECK_VERSION(2, 24, 0) -#endif // UI_BASE_GTK_GTK_COMPAT_H_ +#endif // UI_GFX_GTK_COMPAT_H_ diff --git a/chromium/ui/gfx/gtk_native_view_id_manager.cc b/chromium/ui/gfx/gtk_native_view_id_manager.cc index 07e1ed4c81d..0844b190dd9 100644 --- a/chromium/ui/gfx/gtk_native_view_id_manager.cc +++ b/chromium/ui/gfx/gtk_native_view_id_manager.cc @@ -10,8 +10,8 @@ #include "base/logging.h" #include "base/memory/singleton.h" #include "base/rand_util.h" -#include "ui/base/gtk/gdk_x_compat.h" -#include "ui/base/gtk/gtk_compat.h" +#include "ui/gfx/gdk_compat.h" +#include "ui/gfx/gtk_compat.h" #include "ui/gfx/gtk_preserve_window.h" // ----------------------------------------------------------------------------- diff --git a/chromium/ui/gfx/gtk_native_view_id_manager.h b/chromium/ui/gfx/gtk_native_view_id_manager.h index 7c8afcc0f9d..242cf0939e3 100644 --- a/chromium/ui/gfx/gtk_native_view_id_manager.h +++ b/chromium/ui/gfx/gtk_native_view_id_manager.h @@ -8,7 +8,7 @@ #include <map> #include "base/synchronization/lock.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/native_widget_types.h" template <typename T> struct DefaultSingletonTraits; diff --git a/chromium/ui/gfx/gtk_preserve_window.cc b/chromium/ui/gfx/gtk_preserve_window.cc index 8ea1c431650..78a49c28510 100644 --- a/chromium/ui/gfx/gtk_preserve_window.cc +++ b/chromium/ui/gfx/gtk_preserve_window.cc @@ -7,7 +7,7 @@ #include <gdk/gdk.h> #include <gtk/gtk.h> -#include "ui/base/gtk/gtk_compat.h" +#include "ui/gfx/gtk_compat.h" G_BEGIN_DECLS diff --git a/chromium/ui/gfx/gtk_preserve_window.h b/chromium/ui/gfx/gtk_preserve_window.h index 53a821e44dd..f48be3f2bdb 100644 --- a/chromium/ui/gfx/gtk_preserve_window.h +++ b/chromium/ui/gfx/gtk_preserve_window.h @@ -9,7 +9,7 @@ #include <gdk/gdk.h> #include <gtk/gtk.h> -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" // GtkFixed creates an X window when realized and destroys an X window // when unrealized. GtkPreserveWindow allows overrides this diff --git a/chromium/ui/gfx/gtk_util.h b/chromium/ui/gfx/gtk_util.h index 5fe0c081fca..5672bbd8f12 100644 --- a/chromium/ui/gfx/gtk_util.h +++ b/chromium/ui/gfx/gtk_util.h @@ -8,7 +8,7 @@ #include <vector> #include "base/time/time.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" typedef struct _GdkPixbuf GdkPixbuf; typedef struct _GdkRegion GdkRegion; diff --git a/chromium/ui/gfx/icon_util.h b/chromium/ui/gfx/icon_util.h index 7ce5606f525..d56f5a10df3 100644 --- a/chromium/ui/gfx/icon_util.h +++ b/chromium/ui/gfx/icon_util.h @@ -12,7 +12,7 @@ #include "base/basictypes.h" #include "base/gtest_prod_util.h" #include "base/memory/scoped_ptr.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/point.h" #include "ui/gfx/size.h" diff --git a/chromium/ui/gfx/icon_util_unittest.cc b/chromium/ui/gfx/icon_util_unittest.cc index b1548cee447..641422a24ef 100644 --- a/chromium/ui/gfx/icon_util_unittest.cc +++ b/chromium/ui/gfx/icon_util_unittest.cc @@ -92,7 +92,7 @@ void IconUtilTest::CheckAllIconSizes(const base::FilePath& icon_filename, // Read the file completely into memory. std::string icon_data; - ASSERT_TRUE(file_util::ReadFileToString(icon_filename, &icon_data)); + ASSERT_TRUE(base::ReadFileToString(icon_filename, &icon_data)); ASSERT_GE(icon_data.length(), sizeof(IconUtil::ICONDIR)); // Ensure that it has exactly the expected number and sizes of icons, in the diff --git a/chromium/ui/gfx/image/cairo_cached_surface.h b/chromium/ui/gfx/image/cairo_cached_surface.h index d29d9befd8c..7c0204aa81b 100644 --- a/chromium/ui/gfx/image/cairo_cached_surface.h +++ b/chromium/ui/gfx/image/cairo_cached_surface.h @@ -7,7 +7,7 @@ #include <vector> -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" typedef struct _GdkDisplay GdkDisplay; typedef struct _GdkPixbuf GdkPixbuf; diff --git a/chromium/ui/gfx/image/canvas_image_source.h b/chromium/ui/gfx/image/canvas_image_source.h index a713b95ce8d..8373387326c 100644 --- a/chromium/ui/gfx/image/canvas_image_source.h +++ b/chromium/ui/gfx/image/canvas_image_source.h @@ -7,7 +7,7 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/image/image_skia_source.h" #include "ui/gfx/size.h" diff --git a/chromium/ui/gfx/image/image.cc b/chromium/ui/gfx/image/image.cc index b0733b7ccda..f089c837504 100644 --- a/chromium/ui/gfx/image/image.cc +++ b/chromium/ui/gfx/image/image.cc @@ -22,10 +22,10 @@ #include <gdk-pixbuf/gdk-pixbuf.h> #include <gdk/gdk.h> #include <glib-object.h> -#include "ui/base/gtk/scoped_gobject.h" #include "ui/gfx/canvas.h" #include "ui/gfx/gtk_util.h" #include "ui/gfx/image/cairo_cached_surface.h" +#include "ui/gfx/scoped_gobject.h" #elif defined(OS_IOS) #include "base/mac/foundation_util.h" #include "ui/gfx/image/image_skia_util_ios.h" diff --git a/chromium/ui/gfx/image/image.h b/chromium/ui/gfx/image/image.h index e9619dca21e..00b5baa194b 100644 --- a/chromium/ui/gfx/image/image.h +++ b/chromium/ui/gfx/image/image.h @@ -25,7 +25,7 @@ #include "base/basictypes.h" #include "base/gtest_prod_util.h" #include "base/memory/ref_counted_memory.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/native_widget_types.h" #if defined(OS_MACOSX) && !defined(OS_IOS) diff --git a/chromium/ui/gfx/image/image_family.h b/chromium/ui/gfx/image/image_family.h index 902dedeb419..c7943713676 100644 --- a/chromium/ui/gfx/image/image_family.h +++ b/chromium/ui/gfx/image/image_family.h @@ -9,7 +9,7 @@ #include <map> #include <utility> -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/image/image.h" namespace gfx { diff --git a/chromium/ui/gfx/image/image_png_rep.h b/chromium/ui/gfx/image/image_png_rep.h index 466e37c1ac9..7e5ce5b4e41 100644 --- a/chromium/ui/gfx/image/image_png_rep.h +++ b/chromium/ui/gfx/image/image_png_rep.h @@ -7,7 +7,7 @@ #include "base/memory/ref_counted_memory.h" #include "ui/base/layout.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" namespace gfx { class Size; diff --git a/chromium/ui/gfx/image/image_skia.h b/chromium/ui/gfx/image/image_skia.h index 9d0e9afa88f..4bc21f877cd 100644 --- a/chromium/ui/gfx/image/image_skia.h +++ b/chromium/ui/gfx/image/image_skia.h @@ -11,7 +11,7 @@ #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/image/image_skia_rep.h" namespace gfx { diff --git a/chromium/ui/gfx/image/image_skia_operations.h b/chromium/ui/gfx/image/image_skia_operations.h index 9e397df7e0f..92da50ca1a9 100644 --- a/chromium/ui/gfx/image/image_skia_operations.h +++ b/chromium/ui/gfx/image/image_skia_operations.h @@ -7,8 +7,8 @@ #include "base/gtest_prod_util.h" #include "skia/ext/image_operations.h" -#include "ui/base/ui_export.h" #include "ui/gfx/color_utils.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/shadow_value.h" #include "ui/gfx/skbitmap_operations.h" diff --git a/chromium/ui/gfx/image/image_skia_rep.h b/chromium/ui/gfx/image/image_skia_rep.h index 1314215d242..6fca4111597 100644 --- a/chromium/ui/gfx/image/image_skia_rep.h +++ b/chromium/ui/gfx/image/image_skia_rep.h @@ -7,7 +7,7 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/layout.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/size.h" namespace gfx { diff --git a/chromium/ui/gfx/image/image_skia_source.h b/chromium/ui/gfx/image/image_skia_source.h index 1fff1358717..ed38e1c9389 100644 --- a/chromium/ui/gfx/image/image_skia_source.h +++ b/chromium/ui/gfx/image/image_skia_source.h @@ -6,7 +6,7 @@ #define UI_GFX_IMAGE_IMAGE_SKIA_SOURCE_H_ #include "ui/base/layout.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" namespace gfx { diff --git a/chromium/ui/gfx/image/image_skia_util_ios.h b/chromium/ui/gfx/image/image_skia_util_ios.h index ff4468d94ce..57c9698b955 100644 --- a/chromium/ui/gfx/image/image_skia_util_ios.h +++ b/chromium/ui/gfx/image/image_skia_util_ios.h @@ -6,7 +6,7 @@ #define UI_GFX_IMAGE_IMAGE_SKIA_UTIL_IOS_H_ #include "ui/base/layout.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #ifdef __OBJC__ @class UIImage; diff --git a/chromium/ui/gfx/image/image_skia_util_mac.h b/chromium/ui/gfx/image/image_skia_util_mac.h index 1a4427da89f..10d05b045d4 100644 --- a/chromium/ui/gfx/image/image_skia_util_mac.h +++ b/chromium/ui/gfx/image/image_skia_util_mac.h @@ -7,7 +7,7 @@ #include <ApplicationServices/ApplicationServices.h> -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #ifdef __LP64__ typedef CGSize NSSize; diff --git a/chromium/ui/gfx/image/image_util.h b/chromium/ui/gfx/image/image_util.h index 9ada2fe74ff..a039557a8f0 100644 --- a/chromium/ui/gfx/image/image_util.h +++ b/chromium/ui/gfx/image/image_util.h @@ -8,7 +8,7 @@ #include <vector> #include "base/basictypes.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" namespace gfx { class Image; diff --git a/chromium/ui/gfx/insets.h b/chromium/ui/gfx/insets.h index f9ef4ffc314..571751d937e 100644 --- a/chromium/ui/gfx/insets.h +++ b/chromium/ui/gfx/insets.h @@ -8,7 +8,7 @@ #include <string> #include "build/build_config.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/insets_base.h" #if defined(TOOLKIT_GTK) diff --git a/chromium/ui/gfx/insets_base.h b/chromium/ui/gfx/insets_base.h index bf0b48309bc..ab105bccfb8 100644 --- a/chromium/ui/gfx/insets_base.h +++ b/chromium/ui/gfx/insets_base.h @@ -5,7 +5,7 @@ #ifndef UI_GFX_INSETS_BASE_H_ #define UI_GFX_INSETS_BASE_H_ -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" namespace gfx { diff --git a/chromium/ui/gfx/insets_f.h b/chromium/ui/gfx/insets_f.h index d447d941682..045b8a02e8e 100644 --- a/chromium/ui/gfx/insets_f.h +++ b/chromium/ui/gfx/insets_f.h @@ -8,7 +8,7 @@ #include <string> #include "build/build_config.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/insets_base.h" namespace gfx { diff --git a/chromium/ui/gfx/interpolated_transform.cc b/chromium/ui/gfx/interpolated_transform.cc index 583c27f05b9..b9698b160cd 100644 --- a/chromium/ui/gfx/interpolated_transform.cc +++ b/chromium/ui/gfx/interpolated_transform.cc @@ -11,7 +11,7 @@ #endif #include "base/logging.h" -#include "ui/base/animation/tween.h" +#include "ui/gfx/animation/tween.h" namespace { @@ -125,7 +125,8 @@ inline float InterpolatedTransform::ValueBetween(float time, return end_value; float t = (time - start_time_) / (end_time_ - start_time_); - return static_cast<float>(Tween::ValueBetween(t, start_value, end_value)); + return static_cast<float>( + gfx::Tween::ValueBetween(t, start_value, end_value)); } /////////////////////////////////////////////////////////////////////////////// diff --git a/chromium/ui/gfx/interpolated_transform_unittest.cc b/chromium/ui/gfx/interpolated_transform_unittest.cc index dd31b8b5e2f..acea465d59a 100644 --- a/chromium/ui/gfx/interpolated_transform_unittest.cc +++ b/chromium/ui/gfx/interpolated_transform_unittest.cc @@ -90,10 +90,10 @@ TEST(InterpolatedTransformTest, InterpolatedRotationAboutPivot) { CheckApproximatelyEqual(gfx::Transform(), result); result = interpolated_xform.Interpolate(1.0f); gfx::Point expected_result = pivot; - result.TransformPoint(pivot); + result.TransformPoint(&pivot); EXPECT_EQ(expected_result, pivot); expected_result = gfx::Point(0, 100); - result.TransformPoint(above_pivot); + result.TransformPoint(&above_pivot); EXPECT_EQ(expected_result, above_pivot); } @@ -107,10 +107,10 @@ TEST(InterpolatedTransformTest, InterpolatedScaleAboutPivot) { CheckApproximatelyEqual(gfx::Transform(), result); result = interpolated_xform.Interpolate(1.0f); gfx::Point expected_result = pivot; - result.TransformPoint(pivot); + result.TransformPoint(&pivot); EXPECT_EQ(expected_result, pivot); expected_result = gfx::Point(100, 300); - result.TransformPoint(above_pivot); + result.TransformPoint(&above_pivot); EXPECT_EQ(expected_result, above_pivot); } diff --git a/chromium/ui/gfx/native_widget_types.h b/chromium/ui/gfx/native_widget_types.h index faf3607db92..3d7b9d1cd3b 100644 --- a/chromium/ui/gfx/native_widget_types.h +++ b/chromium/ui/gfx/native_widget_types.h @@ -13,7 +13,7 @@ #include "base/basictypes.h" #include "base/logging.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" // This file provides cross platform typedefs for native widget types. // NativeWindow: this is a handle to a native, top-level window @@ -43,13 +43,12 @@ // 'views'. #if defined(USE_AURA) -#include "ui/base/cursor/cursor.h" - class SkRegion; namespace aura { class Window; } namespace ui { +class Cursor; class Event; } #endif // defined(USE_AURA) diff --git a/chromium/ui/gfx/ozone/OWNERS b/chromium/ui/gfx/ozone/OWNERS new file mode 100644 index 00000000000..77f21b5cae7 --- /dev/null +++ b/chromium/ui/gfx/ozone/OWNERS @@ -0,0 +1 @@ +rjkroege@chromium.org diff --git a/chromium/ui/base/ozone/surface_factory_ozone.cc b/chromium/ui/gfx/ozone/surface_factory_ozone.cc index f082e7dc416..9be61f42877 100644 --- a/chromium/ui/base/ozone/surface_factory_ozone.cc +++ b/chromium/ui/gfx/ozone/surface_factory_ozone.cc @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/ozone/surface_factory_ozone.h" +#include "ui/gfx/ozone/surface_factory_ozone.h" #include <stdlib.h> -namespace ui { +namespace gfx { // static SurfaceFactoryOzone* SurfaceFactoryOzone::impl_ = NULL; @@ -16,7 +16,7 @@ class SurfaceFactoryOzoneStub : public SurfaceFactoryOzone { SurfaceFactoryOzoneStub() {} virtual ~SurfaceFactoryOzoneStub() {} - virtual void InitializeHardware() OVERRIDE {} + virtual HardwareState InitializeHardware() OVERRIDE { return INITIALIZED; } virtual void ShutdownHardware() OVERRIDE {} virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE { return 0; } virtual gfx::AcceleratedWidget RealizeAcceleratedWidget( @@ -57,9 +57,21 @@ const char* SurfaceFactoryOzone::DefaultDisplaySpec() { return "720x1280*2"; } +gfx::Screen* SurfaceFactoryOzone::CreateDesktopScreen() { + return NULL; +} + +intptr_t SurfaceFactoryOzone::GetNativeDisplay() { + return 0; +} + +bool SurfaceFactoryOzone::SchedulePageFlip(gfx::AcceleratedWidget) { + return true; +} + // static SurfaceFactoryOzone* SurfaceFactoryOzone::CreateTestHelper() { return new SurfaceFactoryOzoneStub; } -} // namespace ui +} // namespace gfx diff --git a/chromium/ui/base/ozone/surface_factory_ozone.h b/chromium/ui/gfx/ozone/surface_factory_ozone.h index 50a9b4bdf59..9c5eac23b4f 100644 --- a/chromium/ui/base/ozone/surface_factory_ozone.h +++ b/chromium/ui/gfx/ozone/surface_factory_ozone.h @@ -2,43 +2,54 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_OZONE_SURFACE_LNUX_FACTORY_OZONE_H_ -#define UI_BASE_OZONE_SURFACE_LNUX_FACTORY_OZONE_H_ +#ifndef UI_GFX_OZONE_SURFACE_LNUX_FACTORY_OZONE_H_ +#define UI_GFX_OZONE_SURFACE_LNUX_FACTORY_OZONE_H_ -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/rect.h" namespace gfx { +class Screen; class VSyncProvider; -} // namespace gfx -namespace ui { - -class SurfaceFactoryOzone { +class GFX_EXPORT SurfaceFactoryOzone { public: + // Describes the state of the hardware after initialization. + enum HardwareState { + INITIALIZED, + FAILED, + }; + SurfaceFactoryOzone(); virtual ~SurfaceFactoryOzone(); // Returns the instance - UI_EXPORT static SurfaceFactoryOzone* GetInstance(); + static SurfaceFactoryOzone* GetInstance(); // Returns a display spec as in |CreateDisplayFromSpec| for the default // native surface. virtual const char* DefaultDisplaySpec(); // Sets the implementation delegate. Ownership is retained by the caller. - UI_EXPORT static void SetInstance(SurfaceFactoryOzone* impl); + static void SetInstance(SurfaceFactoryOzone* impl); + + // TODO(rjkroege): decide how to separate screen/display stuff from SFOz + // This method implements gfx::Screen, particularly useful in Desktop Aura. + virtual gfx::Screen* CreateDesktopScreen(); - // TODO(rjkroege): Add a status code if necessary. // Configures the display hardware. Must be called from within the GPU // process before the sandbox has been activated. - virtual void InitializeHardware() = 0; + virtual HardwareState InitializeHardware() = 0; // Cleans up display hardware state. Call this from within the GPU process. // This method must be safe to run inside of the sandbox. virtual void ShutdownHardware() = 0; + // Returns the native EGL display. This is generally needed in creating + // EGL windows. + virtual intptr_t GetNativeDisplay(); + // Obtains an AcceleratedWidget backed by a native Linux framebuffer. // The returned AcceleratedWidget is an opaque token that must realized // before it can be used to create a GL surface. @@ -60,6 +71,10 @@ class SurfaceFactoryOzone { gfx::AcceleratedWidget w, const gfx::Rect& bounds) = 0; + // Called after the appropriate GL swap buffers command. Used if extra work + // is needed to perform the actual buffer swap. + virtual bool SchedulePageFlip(gfx::AcceleratedWidget w); + // Returns a gfx::VsyncProvider for the provided AcceleratedWidget. Note // that this may be called after we have entered the sandbox so if there are // operations (e.g. opening a file descriptor providing vsync events) that @@ -68,13 +83,12 @@ class SurfaceFactoryOzone { virtual gfx::VSyncProvider* GetVSyncProvider(gfx::AcceleratedWidget w) = 0; // Create a default SufaceFactoryOzone implementation useful for tests. - UI_EXPORT static SurfaceFactoryOzone* CreateTestHelper(); + static SurfaceFactoryOzone* CreateTestHelper(); private: static SurfaceFactoryOzone* impl_; // not owned }; -} // namespace ui - +} // namespace gfx -#endif // UI_BASE_OZONE_SURFACE_LNUX_FACTORY_OZONE_H_ +#endif // UI_GFX_OZONE_SURFACE_LNUX_FACTORY_OZONE_H_ diff --git a/chromium/ui/gfx/pango_util.cc b/chromium/ui/gfx/pango_util.cc index 3f96d4b140d..10bd2538742 100644 --- a/chromium/ui/gfx/pango_util.cc +++ b/chromium/ui/gfx/pango_util.cc @@ -34,13 +34,6 @@ namespace { // Marker for accelerators in the text. const gunichar kAcceleratorChar = '&'; -// Multiply by the text height to determine how much text should be faded -// when elliding. -const double kFadeWidthFactor = 1.5; - -// End state of the elliding fade. -const double kFadeFinalAlpha = 0.15; - // Return |cairo_font_options|. If needed, allocate and update it. // TODO(derat): Return font-specific options: http://crbug.com/125235 cairo_font_options_t* GetCairoFontOptions() { @@ -321,28 +314,10 @@ void DrawPangoLayout(cairo_t* cr, cairo_save(cr); - // If we're not eliding, use a fixed color. - // Otherwise, create a gradient pattern to use as the source. - if (text_direction == base::i18n::RIGHT_TO_LEFT || - (flags & gfx::Canvas::NO_ELLIPSIS) || - text_rect.width() <= bounds.width()) { - cairo_set_source_rgba(cr, r, g, b, a); - } else { - // Fade to semi-transparent to elide. - int fade_width = static_cast<double>(text_rect.height()) * kFadeWidthFactor; - if (fade_width > bounds.width() / 2) { - // Don't fade more than half the text. - fade_width = bounds.width() / 2; - } - int fade_x = bounds.x() + bounds.width() - fade_width; - - pattern = cairo_pattern_create_linear( - fade_x, bounds.y(), bounds.x() + bounds.width(), bounds.y()); - cairo_pattern_add_color_stop_rgba(pattern, 0, r, g, b, a); - cairo_pattern_add_color_stop_rgba(pattern, 1, r, g, b, kFadeFinalAlpha); - cairo_set_source(cr, pattern); - } - + // Use a fixed color. + // Note: We do not elide (fade out the text) here, due to a bug in certain + // Linux environments (http://crbug.com/123104). + cairo_set_source_rgba(cr, r, g, b, a); cairo_move_to(cr, text_rect.x(), text_rect.y()); pango_cairo_show_layout(cr, layout); diff --git a/chromium/ui/gfx/pango_util.h b/chromium/ui/gfx/pango_util.h index abb0a7d550e..840163825cd 100644 --- a/chromium/ui/gfx/pango_util.h +++ b/chromium/ui/gfx/pango_util.h @@ -13,7 +13,7 @@ #include "base/logging.h" #include "base/strings/string16.h" #include "third_party/skia/include/core/SkColor.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" typedef struct _PangoContext PangoContext; diff --git a/chromium/ui/gfx/path.h b/chromium/ui/gfx/path.h index 1e8662921c5..f1c7718f9a3 100644 --- a/chromium/ui/gfx/path.h +++ b/chromium/ui/gfx/path.h @@ -7,7 +7,7 @@ #include "base/basictypes.h" #include "third_party/skia/include/core/SkPath.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/native_widget_types.h" namespace gfx { diff --git a/chromium/ui/gfx/path_win.h b/chromium/ui/gfx/path_win.h index 6df025b1bfc..f64bc80a5ef 100644 --- a/chromium/ui/gfx/path_win.h +++ b/chromium/ui/gfx/path_win.h @@ -7,7 +7,7 @@ #include <windows.h> -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" class SkPath; diff --git a/chromium/ui/gfx/path_x11.h b/chromium/ui/gfx/path_x11.h index df3ad623d33..e5a309209cc 100644 --- a/chromium/ui/gfx/path_x11.h +++ b/chromium/ui/gfx/path_x11.h @@ -8,7 +8,7 @@ #include <X11/Xlib.h> #include <X11/Xregion.h> -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" class SkPath; diff --git a/chromium/ui/gfx/platform_font.h b/chromium/ui/gfx/platform_font.h index c5f71202356..09bf8be0b3d 100644 --- a/chromium/ui/gfx/platform_font.h +++ b/chromium/ui/gfx/platform_font.h @@ -9,7 +9,7 @@ #include "base/memory/ref_counted.h" #include "base/strings/string16.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/native_widget_types.h" namespace gfx { diff --git a/chromium/ui/gfx/platform_font_pango.cc b/chromium/ui/gfx/platform_font_pango.cc index b950d23aac1..0ddf363c3f7 100644 --- a/chromium/ui/gfx/platform_font_pango.cc +++ b/chromium/ui/gfx/platform_font_pango.cc @@ -14,10 +14,8 @@ #include "base/strings/string_piece.h" #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" -#include "grit/app_locale_settings.h" #include "third_party/skia/include/core/SkPaint.h" #include "third_party/skia/include/core/SkTypeface.h" -#include "ui/base/l10n/l10n_util.h" #include "ui/gfx/canvas.h" #include "ui/gfx/font.h" #include "ui/gfx/pango_util.h" @@ -60,37 +58,18 @@ std::string FindBestMatchFontFamilyName( return font_family; } -// Returns a Pango font description (suitable for parsing by -// pango_font_description_from_string()) for the default UI font. -std::string GetDefaultFont() { -#if !defined(TOOLKIT_GTK) -#if defined(OS_CHROMEOS) - return l10n_util::GetStringUTF8(IDS_UI_FONT_FAMILY_CROS); -#else - return "sans 10"; -#endif // defined(OS_CHROMEOS) -#else - GtkSettings* settings = gtk_settings_get_default(); - - gchar* font_name = NULL; - g_object_get(settings, "gtk-font-name", &font_name, NULL); - - // Temporary CHECK for helping track down - // http://code.google.com/p/chromium/issues/detail?id=12530 - CHECK(font_name) << " Unable to get gtk-font-name for default font."; - - std::string default_font = std::string(font_name); - g_free(font_name); - return default_font; -#endif // !defined(TOOLKIT_GTK) -} - } // namespace namespace gfx { +// static Font* PlatformFontPango::default_font_ = NULL; +#if defined(OS_CHROMEOS) +// static +std::string* PlatformFontPango::default_font_description_ = NULL; +#endif + //////////////////////////////////////////////////////////////////////////////// // PlatformFontPango, public: @@ -154,6 +133,16 @@ void PlatformFontPango::ReloadDefaultFont() { default_font_ = NULL; } +#if defined(OS_CHROMEOS) +// static +void PlatformFontPango::SetDefaultFontDescription( + const std::string& font_description) { + delete default_font_description_; + default_font_description_ = new std::string(font_description); +} + +#endif + Font PlatformFontPango::DeriveFont(int size_delta, int style) const { // If the delta is negative, if must not push the size below 1 if (size_delta < 0) @@ -261,6 +250,33 @@ PlatformFontPango::PlatformFontPango(const skia::RefPtr<SkTypeface>& typeface, PlatformFontPango::~PlatformFontPango() {} +// static +std::string PlatformFontPango::GetDefaultFont() { +#if !defined(TOOLKIT_GTK) +#if defined(OS_CHROMEOS) + // Font name must have been provided by way of SetDefaultFontDescription(). + CHECK(default_font_description_); + return *default_font_description_; +#else + return "sans 10"; +#endif // defined(OS_CHROMEOS) +#else + GtkSettings* settings = gtk_settings_get_default(); + + gchar* font_name = NULL; + g_object_get(settings, "gtk-font-name", &font_name, NULL); + + // Temporary CHECK for helping track down + // http://code.google.com/p/chromium/issues/detail?id=12530 + CHECK(font_name) << " Unable to get gtk-font-name for default font."; + + std::string default_font = std::string(font_name); + g_free(font_name); + return default_font; +#endif // !defined(TOOLKIT_GTK) +} + + void PlatformFontPango::InitWithNameAndSize(const std::string& font_name, int font_size) { DCHECK_GT(font_size, 0); diff --git a/chromium/ui/gfx/platform_font_pango.h b/chromium/ui/gfx/platform_font_pango.h index 2fce305a1b7..1804f37ddd3 100644 --- a/chromium/ui/gfx/platform_font_pango.h +++ b/chromium/ui/gfx/platform_font_pango.h @@ -5,6 +5,8 @@ #ifndef UI_GFX_PLATFORM_FONT_PANGO_H_ #define UI_GFX_PLATFORM_FONT_PANGO_H_ +#include <string> + #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "skia/ext/refptr.h" @@ -31,6 +33,11 @@ class UI_EXPORT PlatformFontPango : public PlatformFont { // the locale has changed. static void ReloadDefaultFont(); +#if defined(OS_CHROMEOS) + // Sets the default font. + static void SetDefaultFontDescription(const std::string& font_description); +#endif + // Position as an offset from the height of the drawn text, used to draw // an underline. This is a negative number, so the underline would be // drawn at y + height + underline_position. @@ -59,6 +66,10 @@ class UI_EXPORT PlatformFontPango : public PlatformFont { int style); virtual ~PlatformFontPango(); + // Returns a Pango font description (suitable for parsing by + // pango_font_description_from_string()) for the default UI font. + static std::string GetDefaultFont(); + // Initialize this object. void InitWithNameAndSize(const std::string& font_name, int font_size); void InitWithTypefaceNameSizeAndStyle( @@ -102,6 +113,10 @@ class UI_EXPORT PlatformFontPango : public PlatformFont { // The default font, used for the default constructor. static Font* default_font_; +#if defined(OS_CHROMEOS) + static std::string* default_font_description_; +#endif + DISALLOW_COPY_AND_ASSIGN(PlatformFontPango); }; diff --git a/chromium/ui/gfx/platform_font_pango_unittest.cc b/chromium/ui/gfx/platform_font_pango_unittest.cc index 228c66b0201..f30e584c9b2 100644 --- a/chromium/ui/gfx/platform_font_pango_unittest.cc +++ b/chromium/ui/gfx/platform_font_pango_unittest.cc @@ -21,8 +21,10 @@ namespace gfx { // Test that PlatformFontPango is able to cope with PangoFontDescriptions // containing multiple font families. The first family should be preferred. TEST(PlatformFontPangoTest, FamilyList) { - // Needed for GLib versions prior to 2.36. + // Needed for GLib versions prior to 2.36, but deprecated starting 2.35. +#if !GLIB_CHECK_VERSION(2, 35, 0) g_type_init(); +#endif ScopedPangoFontDescription desc( pango_font_description_from_string("Arial,Times New Roman, 13px")); diff --git a/chromium/ui/gfx/platform_font_win.cc b/chromium/ui/gfx/platform_font_win.cc index 4a792f6ad86..2d4c006f268 100644 --- a/chromium/ui/gfx/platform_font_win.cc +++ b/chromium/ui/gfx/platform_font_win.cc @@ -17,9 +17,9 @@ #include "base/win/scoped_hdc.h" #include "base/win/scoped_select_object.h" #include "base/win/win_util.h" -#include "ui/base/win/scoped_set_map_mode.h" #include "ui/gfx/canvas.h" #include "ui/gfx/font.h" +#include "ui/gfx/win/scoped_set_map_mode.h" namespace { @@ -229,7 +229,7 @@ PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRef(HFONT font) { { base::win::ScopedGetDC screen_dc(NULL); base::win::ScopedSelectObject scoped_font(screen_dc, font); - ui::ScopedSetMapMode mode(screen_dc, MM_TEXT); + gfx::ScopedSetMapMode mode(screen_dc, MM_TEXT); GetTextMetrics(screen_dc, &font_metrics); } @@ -284,7 +284,7 @@ int PlatformFontWin::HFontRef::GetDluBaseX() { base::win::ScopedGetDC screen_dc(NULL); base::win::ScopedSelectObject font(screen_dc, hfont_); - ui::ScopedSetMapMode mode(screen_dc, MM_TEXT); + gfx::ScopedSetMapMode mode(screen_dc, MM_TEXT); // Yes, this is how Microsoft recommends calculating the dialog unit // conversions. See: http://support.microsoft.com/kb/125681 diff --git a/chromium/ui/gfx/platform_font_win.h b/chromium/ui/gfx/platform_font_win.h index 568bf952b35..ffa82499d45 100644 --- a/chromium/ui/gfx/platform_font_win.h +++ b/chromium/ui/gfx/platform_font_win.h @@ -9,7 +9,7 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/platform_font.h" namespace gfx { diff --git a/chromium/ui/gfx/point.h b/chromium/ui/gfx/point.h index 0f8a327c5c8..cb233da5274 100644 --- a/chromium/ui/gfx/point.h +++ b/chromium/ui/gfx/point.h @@ -5,7 +5,7 @@ #ifndef UI_GFX_POINT_H_ #define UI_GFX_POINT_H_ -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/point_base.h" #include "ui/gfx/point_f.h" #include "ui/gfx/vector2d.h" diff --git a/chromium/ui/gfx/point3_f.h b/chromium/ui/gfx/point3_f.h index 8c700df47a7..5ea0c3181f0 100644 --- a/chromium/ui/gfx/point3_f.h +++ b/chromium/ui/gfx/point3_f.h @@ -7,7 +7,7 @@ #include <string> -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/point_f.h" #include "ui/gfx/vector3d_f.h" diff --git a/chromium/ui/gfx/point_base.h b/chromium/ui/gfx/point_base.h index 048b0930b2d..17f1d5183c4 100644 --- a/chromium/ui/gfx/point_base.h +++ b/chromium/ui/gfx/point_base.h @@ -9,7 +9,7 @@ #include "base/compiler_specific.h" #include "build/build_config.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" namespace gfx { diff --git a/chromium/ui/gfx/point_f.h b/chromium/ui/gfx/point_f.h index a7b841f23db..d9fc18cbbcc 100644 --- a/chromium/ui/gfx/point_f.h +++ b/chromium/ui/gfx/point_f.h @@ -7,7 +7,7 @@ #include <string> -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/point_base.h" #include "ui/gfx/vector2d_f.h" diff --git a/chromium/ui/gfx/quad_f.h b/chromium/ui/gfx/quad_f.h index 4173dbe0f2f..5bbc3cd40dd 100644 --- a/chromium/ui/gfx/quad_f.h +++ b/chromium/ui/gfx/quad_f.h @@ -5,10 +5,11 @@ #ifndef UI_GFX_QUAD_F_H_ #define UI_GFX_QUAD_F_H_ +#include <algorithm> #include <cmath> #include <string> -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/point_f.h" #include "ui/gfx/rect_f.h" diff --git a/chromium/ui/base/range/OWNERS b/chromium/ui/gfx/range/OWNERS index 14fce2ae686..14fce2ae686 100644 --- a/chromium/ui/base/range/OWNERS +++ b/chromium/ui/gfx/range/OWNERS diff --git a/chromium/ui/base/range/range.cc b/chromium/ui/gfx/range/range.cc index 75325646a73..1c3968aa6e2 100644 --- a/chromium/ui/base/range/range.cc +++ b/chromium/ui/gfx/range/range.cc @@ -2,15 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/range/range.h" +#include "ui/gfx/range/range.h" +#include <algorithm> #include <limits> #include "base/format_macros.h" #include "base/logging.h" #include "base/strings/stringprintf.h" -namespace ui { +namespace gfx { Range::Range() : start_(0), @@ -80,4 +81,8 @@ std::string Range::ToString() const { return base::StringPrintf("{%" PRIuS ",%" PRIuS "}", start(), end()); } +std::ostream& operator<<(std::ostream& os, const Range& range) { + return os << range.ToString(); +} + } // namespace gfx diff --git a/chromium/ui/base/range/range.h b/chromium/ui/gfx/range/range.h index b8bf4786824..c41c98c8d03 100644 --- a/chromium/ui/base/range/range.h +++ b/chromium/ui/gfx/range/range.h @@ -2,13 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_RANGE_RANGE_H_ -#define UI_BASE_RANGE_RANGE_H_ +#ifndef UI_GFX_RANGE_RANGE_H_ +#define UI_GFX_RANGE_RANGE_H_ +#include <ostream> #include <string> #include "base/basictypes.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #if defined(OS_MACOSX) #if __OBJC__ @@ -23,7 +24,7 @@ typedef struct _NSRange NSRange; #include <richedit.h> #endif -namespace ui { +namespace gfx { // A Range contains two integer values that represent a numeric range, like the // range of characters in a text selection. A range is made of a start and end @@ -109,6 +110,8 @@ class UI_EXPORT Range { size_t end_; }; -} // namespace ui +UI_EXPORT std::ostream& operator<<(std::ostream& os, const Range& range); -#endif // UI_BASE_RANGE_RANGE_H_ +} // namespace gfx + +#endif // UI_GFX_RANGE_RANGE_H_ diff --git a/chromium/ui/base/range/range_mac.mm b/chromium/ui/gfx/range/range_mac.mm index e99db374c90..3f78fb618e3 100644 --- a/chromium/ui/base/range/range_mac.mm +++ b/chromium/ui/gfx/range/range_mac.mm @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/range/range.h" +#include "ui/gfx/range/range.h" #include <limits> #include "base/logging.h" -namespace ui { +namespace gfx { Range::Range(const NSRange& range) { *this = range; diff --git a/chromium/ui/base/range/range_mac_unittest.mm b/chromium/ui/gfx/range/range_mac_unittest.mm index 3142540f04b..c04cbfe9503 100644 --- a/chromium/ui/base/range/range_mac_unittest.mm +++ b/chromium/ui/gfx/range/range_mac_unittest.mm @@ -3,11 +3,11 @@ // found in the LICENSE file. #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/range/range.h" +#include "ui/gfx/range/range.h" TEST(RangeTest, FromNSRange) { NSRange nsr = NSMakeRange(10, 3); - ui::Range r(nsr); + gfx::Range r(nsr); EXPECT_EQ(nsr.location, r.start()); EXPECT_EQ(13U, r.end()); EXPECT_EQ(nsr.length, r.length()); @@ -16,14 +16,14 @@ TEST(RangeTest, FromNSRange) { } TEST(RangeTest, ToNSRange) { - ui::Range r(10, 12); + gfx::Range r(10, 12); NSRange nsr = r.ToNSRange(); EXPECT_EQ(10U, nsr.location); EXPECT_EQ(2U, nsr.length); } TEST(RangeTest, ReversedToNSRange) { - ui::Range r(20, 10); + gfx::Range r(20, 10); NSRange nsr = r.ToNSRange(); EXPECT_EQ(10U, nsr.location); EXPECT_EQ(10U, nsr.length); @@ -31,12 +31,12 @@ TEST(RangeTest, ReversedToNSRange) { TEST(RangeTest, FromNSRangeInvalid) { NSRange nsr = NSMakeRange(NSNotFound, 0); - ui::Range r(nsr); + gfx::Range r(nsr); EXPECT_FALSE(r.IsValid()); } TEST(RangeTest, ToNSRangeInvalid) { - ui::Range r(ui::Range::InvalidRange()); + gfx::Range r(gfx::Range::InvalidRange()); NSRange nsr = r.ToNSRange(); EXPECT_EQ(NSNotFound, nsr.location); EXPECT_EQ(0U, nsr.length); diff --git a/chromium/ui/base/range/range_unittest.cc b/chromium/ui/gfx/range/range_unittest.cc index 95bc54eb843..0afaa405ca4 100644 --- a/chromium/ui/base/range/range_unittest.cc +++ b/chromium/ui/gfx/range/range_unittest.cc @@ -3,10 +3,10 @@ // found in the LICENSE file. #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/range/range.h" +#include "ui/gfx/range/range.h" TEST(RangeTest, EmptyInit) { - ui::Range r; + gfx::Range r; EXPECT_EQ(0U, r.start()); EXPECT_EQ(0U, r.end()); EXPECT_EQ(0U, r.length()); @@ -18,7 +18,7 @@ TEST(RangeTest, EmptyInit) { } TEST(RangeTest, StartEndInit) { - ui::Range r(10, 15); + gfx::Range r(10, 15); EXPECT_EQ(10U, r.start()); EXPECT_EQ(15U, r.end()); EXPECT_EQ(5U, r.length()); @@ -30,7 +30,7 @@ TEST(RangeTest, StartEndInit) { } TEST(RangeTest, StartEndReversedInit) { - ui::Range r(10, 5); + gfx::Range r(10, 5); EXPECT_EQ(10U, r.start()); EXPECT_EQ(5U, r.end()); EXPECT_EQ(5U, r.length()); @@ -42,7 +42,7 @@ TEST(RangeTest, StartEndReversedInit) { } TEST(RangeTest, PositionInit) { - ui::Range r(12); + gfx::Range r(12); EXPECT_EQ(12U, r.start()); EXPECT_EQ(12U, r.end()); EXPECT_EQ(0U, r.length()); @@ -54,7 +54,7 @@ TEST(RangeTest, PositionInit) { } TEST(RangeTest, InvalidRange) { - ui::Range r(ui::Range::InvalidRange()); + gfx::Range r(gfx::Range::InvalidRange()); EXPECT_EQ(0U, r.length()); EXPECT_EQ(r.start(), r.end()); EXPECT_FALSE(r.is_reversed()); @@ -63,32 +63,32 @@ TEST(RangeTest, InvalidRange) { } TEST(RangeTest, Equality) { - ui::Range r1(10, 4); - ui::Range r2(10, 4); - ui::Range r3(10, 2); + gfx::Range r1(10, 4); + gfx::Range r2(10, 4); + gfx::Range r3(10, 2); EXPECT_EQ(r1, r2); EXPECT_NE(r1, r3); EXPECT_NE(r2, r3); - ui::Range r4(11, 4); + gfx::Range r4(11, 4); EXPECT_NE(r1, r4); EXPECT_NE(r2, r4); EXPECT_NE(r3, r4); - ui::Range r5(12, 5); + gfx::Range r5(12, 5); EXPECT_NE(r1, r5); EXPECT_NE(r2, r5); EXPECT_NE(r3, r5); } TEST(RangeTest, EqualsIgnoringDirection) { - ui::Range r1(10, 5); - ui::Range r2(5, 10); + gfx::Range r1(10, 5); + gfx::Range r2(5, 10); EXPECT_TRUE(r1.EqualsIgnoringDirection(r2)); } TEST(RangeTest, SetStart) { - ui::Range r(10, 20); + gfx::Range r(10, 20); EXPECT_EQ(10U, r.start()); EXPECT_EQ(10U, r.length()); @@ -100,7 +100,7 @@ TEST(RangeTest, SetStart) { } TEST(RangeTest, SetEnd) { - ui::Range r(10, 13); + gfx::Range r(10, 13); EXPECT_EQ(10U, r.start()); EXPECT_EQ(3U, r.length()); @@ -111,7 +111,7 @@ TEST(RangeTest, SetEnd) { } TEST(RangeTest, SetStartAndEnd) { - ui::Range r; + gfx::Range r; r.set_end(5); r.set_start(1); EXPECT_EQ(1U, r.start()); @@ -122,7 +122,7 @@ TEST(RangeTest, SetStartAndEnd) { } TEST(RangeTest, ReversedRange) { - ui::Range r(10, 5); + gfx::Range r(10, 5); EXPECT_EQ(10U, r.start()); EXPECT_EQ(5U, r.end()); EXPECT_EQ(5U, r.length()); @@ -133,7 +133,7 @@ TEST(RangeTest, ReversedRange) { } TEST(RangeTest, SetReversedRange) { - ui::Range r(10, 20); + gfx::Range r(10, 20); r.set_start(25); EXPECT_EQ(25U, r.start()); EXPECT_EQ(20U, r.end()); @@ -150,12 +150,12 @@ TEST(RangeTest, SetReversedRange) { EXPECT_EQ(25U, r.GetMax()); } -void TestContainsAndIntersects(const ui::Range& r1, - const ui::Range& r2, - const ui::Range& r3) { +void TestContainsAndIntersects(const gfx::Range& r1, + const gfx::Range& r2, + const gfx::Range& r3) { EXPECT_TRUE(r1.Intersects(r1)); EXPECT_TRUE(r1.Contains(r1)); - EXPECT_EQ(ui::Range(10, 12), r1.Intersect(r1)); + EXPECT_EQ(gfx::Range(10, 12), r1.Intersect(r1)); EXPECT_FALSE(r1.Intersects(r2)); EXPECT_FALSE(r1.Contains(r2)); @@ -168,36 +168,36 @@ void TestContainsAndIntersects(const ui::Range& r1, EXPECT_TRUE(r3.Intersects(r1)); EXPECT_TRUE(r3.Contains(r1)); EXPECT_FALSE(r1.Contains(r3)); - EXPECT_EQ(ui::Range(10, 12), r1.Intersect(r3)); - EXPECT_EQ(ui::Range(10, 12), r3.Intersect(r1)); + EXPECT_EQ(gfx::Range(10, 12), r1.Intersect(r3)); + EXPECT_EQ(gfx::Range(10, 12), r3.Intersect(r1)); EXPECT_TRUE(r2.Intersects(r3)); EXPECT_TRUE(r3.Intersects(r2)); EXPECT_FALSE(r3.Contains(r2)); EXPECT_FALSE(r2.Contains(r3)); - EXPECT_EQ(ui::Range(5, 8), r2.Intersect(r3)); - EXPECT_EQ(ui::Range(5, 8), r3.Intersect(r2)); + EXPECT_EQ(gfx::Range(5, 8), r2.Intersect(r3)); + EXPECT_EQ(gfx::Range(5, 8), r3.Intersect(r2)); } TEST(RangeTest, ContainAndIntersect) { { SCOPED_TRACE("contain and intersect"); - ui::Range r1(10, 12); - ui::Range r2(1, 8); - ui::Range r3(5, 12); + gfx::Range r1(10, 12); + gfx::Range r2(1, 8); + gfx::Range r3(5, 12); TestContainsAndIntersects(r1, r2, r3); } { SCOPED_TRACE("contain and intersect: reversed"); - ui::Range r1(12, 10); - ui::Range r2(8, 1); - ui::Range r3(12, 5); + gfx::Range r1(12, 10); + gfx::Range r2(8, 1); + gfx::Range r3(12, 5); TestContainsAndIntersects(r1, r2, r3); } // Invalid rect tests - ui::Range r1(10, 12); - ui::Range r2(8, 1); - ui::Range invalid = r1.Intersect(r2); + gfx::Range r1(10, 12); + gfx::Range r2(8, 1); + gfx::Range invalid = r1.Intersect(r2); EXPECT_FALSE(invalid.IsValid()); EXPECT_FALSE(invalid.Contains(invalid)); EXPECT_FALSE(invalid.Contains(r1)); diff --git a/chromium/ui/base/range/range_win.cc b/chromium/ui/gfx/range/range_win.cc index 29178b347c3..1180e1bf7a8 100644 --- a/chromium/ui/base/range/range_win.cc +++ b/chromium/ui/gfx/range/range_win.cc @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/range/range.h" +#include "ui/gfx/range/range.h" #include <limits> #include "base/logging.h" -namespace ui { +namespace gfx { Range::Range(const CHARRANGE& range, LONG total_length) { // Check if this is an invalid range. diff --git a/chromium/ui/base/range/range_win_unittest.cc b/chromium/ui/gfx/range/range_win_unittest.cc index 4122d0668dd..f7a442c5bbf 100644 --- a/chromium/ui/base/range/range_win_unittest.cc +++ b/chromium/ui/gfx/range/range_win_unittest.cc @@ -3,11 +3,11 @@ // found in the LICENSE file. #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/range/range.h" +#include "ui/gfx/range/range.h" TEST(RangeTest, FromCHARRANGE) { CHARRANGE cr = { 10, 32 }; - ui::Range r(cr, 50); + gfx::Range r(cr, 50); EXPECT_EQ(10U, r.start()); EXPECT_EQ(32U, r.end()); EXPECT_EQ(22U, r.length()); @@ -17,7 +17,7 @@ TEST(RangeTest, FromCHARRANGE) { TEST(RangeTest, FromReversedCHARRANGE) { CHARRANGE cr = { 20, 10 }; - ui::Range r(cr, 40); + gfx::Range r(cr, 40); EXPECT_EQ(20U, r.start()); EXPECT_EQ(10U, r.end()); EXPECT_EQ(10U, r.length()); @@ -27,7 +27,7 @@ TEST(RangeTest, FromReversedCHARRANGE) { TEST(RangeTest, FromCHARRANGETotal) { CHARRANGE cr = { 0, -1 }; - ui::Range r(cr, 20); + gfx::Range r(cr, 20); EXPECT_EQ(0U, r.start()); EXPECT_EQ(20U, r.end()); EXPECT_EQ(20U, r.length()); @@ -36,14 +36,14 @@ TEST(RangeTest, FromCHARRANGETotal) { } TEST(RangeTest, ToCHARRANGE) { - ui::Range r(10, 30); + gfx::Range r(10, 30); CHARRANGE cr = r.ToCHARRANGE(); EXPECT_EQ(10, cr.cpMin); EXPECT_EQ(30, cr.cpMax); } TEST(RangeTest, ReversedToCHARRANGE) { - ui::Range r(20, 10); + gfx::Range r(20, 10); CHARRANGE cr = r.ToCHARRANGE(); EXPECT_EQ(20U, cr.cpMin); EXPECT_EQ(10U, cr.cpMax); @@ -51,12 +51,12 @@ TEST(RangeTest, ReversedToCHARRANGE) { TEST(RangeTest, FromCHARRANGEInvalid) { CHARRANGE cr = { -1, -1 }; - ui::Range r(cr, 30); + gfx::Range r(cr, 30); EXPECT_FALSE(r.IsValid()); } TEST(RangeTest, ToCHARRANGEInvalid) { - ui::Range r(ui::Range::InvalidRange()); + gfx::Range r(gfx::Range::InvalidRange()); CHARRANGE cr = r.ToCHARRANGE(); EXPECT_EQ(-1, cr.cpMin); EXPECT_EQ(-1, cr.cpMax); diff --git a/chromium/ui/gfx/rect_conversions.cc b/chromium/ui/gfx/rect_conversions.cc index ac7767b3204..a54a49a23d6 100644 --- a/chromium/ui/gfx/rect_conversions.cc +++ b/chromium/ui/gfx/rect_conversions.cc @@ -4,6 +4,7 @@ #include "ui/gfx/rect_conversions.h" +#include <algorithm> #include <cmath> #include "base/logging.h" diff --git a/chromium/ui/gfx/render_text.cc b/chromium/ui/gfx/render_text.cc index 1fcf18cede4..47f42e37cb6 100644 --- a/chromium/ui/gfx/render_text.cc +++ b/chromium/ui/gfx/render_text.cc @@ -13,12 +13,12 @@ #include "third_party/icu/source/common/unicode/utf16.h" #include "third_party/skia/include/core/SkTypeface.h" #include "third_party/skia/include/effects/SkGradientShader.h" -#include "ui/base/text/text_elider.h" -#include "ui/base/text/utf16_indexing.h" #include "ui/gfx/canvas.h" #include "ui/gfx/insets.h" #include "ui/gfx/skia_util.h" #include "ui/gfx/text_constants.h" +#include "ui/gfx/text_elider.h" +#include "ui/gfx/utf16_indexing.h" namespace gfx { @@ -288,8 +288,8 @@ StyleIterator::StyleIterator(const BreakList<SkColor>& colors, StyleIterator::~StyleIterator() {} -ui::Range StyleIterator::GetRange() const { - ui::Range range(colors_.GetRange(color_)); +Range StyleIterator::GetRange() const { + Range range(colors_.GetRange(color_)); for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) range = range.Intersect(styles_[i].GetRange(style_[i])); return range; @@ -301,6 +301,14 @@ void StyleIterator::UpdatePosition(size_t position) { style_[i] = styles_[i].GetBreak(position); } +LineSegment::LineSegment() : run(0) {} + +LineSegment::~LineSegment() {} + +Line::Line() : preceding_heights(0), baseline(0) {} + +Line::~Line() {} + } // namespace internal RenderText::~RenderText() { @@ -308,6 +316,8 @@ RenderText::~RenderText() { void RenderText::SetText(const base::string16& text) { DCHECK(!composition_range_.IsValid()); + if (text_ == text) + return; text_ = text; // Adjust ranged styles and colors to accommodate a new text length. @@ -394,9 +404,18 @@ void RenderText::SetObscuredRevealIndex(int index) { ResetLayout(); } +void RenderText::SetMultiline(bool multiline) { + if (multiline != multiline_) { + multiline_ = multiline; + cached_bounds_and_offset_valid_ = false; + lines_.clear(); + } +} + void RenderText::SetDisplayRect(const Rect& r) { display_rect_ = r; cached_bounds_and_offset_valid_ = false; + lines_.clear(); } void RenderText::SetCursorPosition(size_t position) { @@ -431,8 +450,8 @@ void RenderText::MoveCursor(BreakType break_type, bool RenderText::MoveCursorTo(const SelectionModel& model) { // Enforce valid selection model components. size_t text_length = text().length(); - ui::Range range(std::min(model.selection().start(), text_length), - std::min(model.caret_pos(), text_length)); + Range range(std::min(model.selection().start(), text_length), + std::min(model.caret_pos(), text_length)); // The current model only supports caret positions at valid character indices. if (!IsCursorablePosition(range.start()) || !IsCursorablePosition(range.end())) @@ -450,9 +469,9 @@ bool RenderText::MoveCursorTo(const Point& point, bool select) { return MoveCursorTo(position); } -bool RenderText::SelectRange(const ui::Range& range) { - ui::Range sel(std::min(range.start(), text().length()), - std::min(range.end(), text().length())); +bool RenderText::SelectRange(const Range& range) { + Range sel(std::min(range.start(), text().length()), + std::min(range.end(), text().length())); if (!IsCursorablePosition(sel.start()) || !IsCursorablePosition(sel.end())) return false; LogicalCursorDirection affinity = @@ -476,7 +495,7 @@ void RenderText::ClearSelection() { void RenderText::SelectAll(bool reversed) { const size_t length = text().length(); - const ui::Range all = reversed ? ui::Range(length, 0) : ui::Range(0, length); + const Range all = reversed ? Range(length, 0) : Range(0, length); const bool success = SelectRange(all); DCHECK(success); } @@ -517,13 +536,13 @@ void RenderText::SelectWord() { MoveCursorTo(reversed ? selection_min : selection_max, true); } -const ui::Range& RenderText::GetCompositionRange() const { +const Range& RenderText::GetCompositionRange() const { return composition_range_; } -void RenderText::SetCompositionRange(const ui::Range& composition_range) { +void RenderText::SetCompositionRange(const Range& composition_range) { CHECK(!composition_range.IsValid() || - ui::Range(0, text_.length()).Contains(composition_range)); + Range(0, text_.length()).Contains(composition_range)); composition_range_.set_end(composition_range.end()); composition_range_.set_start(composition_range.start()); ResetLayout(); @@ -539,7 +558,7 @@ void RenderText::SetColor(SkColor value) { #endif } -void RenderText::ApplyColor(SkColor value, const ui::Range& range) { +void RenderText::ApplyColor(SkColor value, const Range& range) { colors_.ApplyValue(value, range); #if defined(OS_WIN) @@ -564,9 +583,7 @@ void RenderText::SetStyle(TextStyle style, bool value) { } } -void RenderText::ApplyStyle(TextStyle style, - bool value, - const ui::Range& range) { +void RenderText::ApplyStyle(TextStyle style, bool value, const Range& range) { styles_[style].ApplyValue(value, range); // Only invalidate the layout on font changes; not for colors or decorations. @@ -686,6 +703,10 @@ void RenderText::DrawSelectedTextForDrag(Canvas* canvas) { Rect RenderText::GetCursorBounds(const SelectionModel& caret, bool insert_mode) { + // TODO(ckocagil): Support multiline. This function should return the height + // of the line the cursor is on. |GetStringSize()| now returns + // the multiline size, eliminate its use here. + EnsureLayout(); size_t caret_pos = caret.caret_pos(); @@ -704,7 +725,7 @@ Rect RenderText::GetCursorBounds(const SelectionModel& caret, } else { size_t grapheme_start = (caret_affinity == CURSOR_FORWARD) ? caret_pos : IndexOfAdjacentGrapheme(caret_pos, CURSOR_BACKWARD); - ui::Range xspan(GetGlyphBounds(grapheme_start)); + Range xspan(GetGlyphBounds(grapheme_start)); if (insert_mode) { x = (caret_affinity == CURSOR_BACKWARD) ? xspan.end() : xspan.start(); } else { // overtype mode @@ -745,7 +766,7 @@ size_t RenderText::IndexOfAdjacentGrapheme(size_t index, } SelectionModel RenderText::GetSelectionModelForSelectionStart() { - const ui::Range& sel = selection(); + const Range& sel = selection(); if (sel.is_empty()) return selection_model_; return SelectionModel(sel.start(), @@ -768,13 +789,14 @@ RenderText::RenderText() selection_color_(kDefaultColor), selection_background_focused_color_(kDefaultSelectionBackgroundColor), focused_(false), - composition_range_(ui::Range::InvalidRange()), + composition_range_(Range::InvalidRange()), colors_(kDefaultColor), styles_(NUM_TEXT_STYLES), composition_and_selection_styles_applied_(false), obscured_(false), obscured_reveal_index_(-1), truncate_length_(0), + multiline_(false), fade_head_(false), fade_tail_(false), background_is_transparent_(false), @@ -818,6 +840,26 @@ const base::string16& RenderText::GetLayoutText() const { return layout_text_.empty() ? text_ : layout_text_; } +const BreakList<size_t>& RenderText::GetLineBreaks() { + if (line_breaks_.max() != 0) + return line_breaks_; + + const string16& layout_text = GetLayoutText(); + const size_t text_length = layout_text.length(); + line_breaks_.SetValue(0); + line_breaks_.SetMax(text_length); + base::i18n::BreakIterator iter(layout_text, + base::i18n::BreakIterator::BREAK_LINE); + const bool success = iter.Init(); + DCHECK(success); + if (success) { + do { + line_breaks_.ApplyValue(iter.pos(), Range(iter.pos(), text_length)); + } while (iter.Advance()); + } + return line_breaks_; +} + void RenderText::ApplyCompositionAndSelectionStyles() { // Save the underline and color breaks to undo the temporary styles later. DCHECK(!composition_and_selection_styles_applied_); @@ -830,7 +872,7 @@ void RenderText::ApplyCompositionAndSelectionStyles() { // Apply the selected text color to the [un-reversed] selection range. if (!selection().is_empty()) { - const ui::Range range(selection().GetMin(), selection().GetMax()); + const Range range(selection().GetMin(), selection().GetMax()); colors_.ApplyValue(selection_color_, range); } composition_and_selection_styles_applied_ = true; @@ -844,25 +886,81 @@ void RenderText::UndoCompositionAndSelectionStyles() { composition_and_selection_styles_applied_ = false; } -Vector2d RenderText::GetTextOffset() { +Vector2d RenderText::GetLineOffset(size_t line_number) { Vector2d offset = display_rect().OffsetFromOrigin(); - offset.Add(GetUpdatedDisplayOffset()); - offset.Add(GetAlignmentOffset()); + // TODO(ckocagil): Apply the display offset for multiline scrolling. + if (!multiline()) + offset.Add(GetUpdatedDisplayOffset()); + else + offset.Add(Vector2d(0, lines_[line_number].preceding_heights)); + offset.Add(GetAlignmentOffset(line_number)); return offset; } Point RenderText::ToTextPoint(const Point& point) { - return point - GetTextOffset(); + return point - GetLineOffset(0); + // TODO(ckocagil): Convert multiline view space points to text space. } Point RenderText::ToViewPoint(const Point& point) { - return point + GetTextOffset(); + if (!multiline()) + return point + GetLineOffset(0); + + // TODO(ckocagil): Traverse individual line segments for RTL support. + DCHECK(!lines_.empty()); + int x = point.x(); + size_t line = 0; + for (; line < lines_.size() && x > lines_[line].size.width(); ++line) + x -= lines_[line].size.width(); + return Point(x, point.y()) + GetLineOffset(line); } -Vector2d RenderText::GetAlignmentOffset() { +std::vector<Rect> RenderText::TextBoundsToViewBounds(const Range& x) { + std::vector<Rect> rects; + + if (!multiline()) { + rects.push_back(Rect(ToViewPoint(Point(x.GetMin(), 0)), + Size(x.length(), GetStringSize().height()))); + return rects; + } + + EnsureLayout(); + + // Each line segment keeps its position in text coordinates. Traverse all line + // segments and if the segment intersects with the given range, add the view + // rect corresponding to the intersection to |rects|. + for (size_t line = 0; line < lines_.size(); ++line) { + int line_x = 0; + const Vector2d offset = GetLineOffset(line); + for (size_t i = 0; i < lines_[line].segments.size(); ++i) { + const internal::LineSegment* segment = &lines_[line].segments[i]; + const Range intersection = segment->x_range.Intersect(x); + if (!intersection.is_empty()) { + Rect rect(line_x + intersection.start() - segment->x_range.start(), + 0, intersection.length(), lines_[line].size.height()); + rects.push_back(rect + offset); + } + line_x += segment->x_range.length(); + } + } + + return rects; +} + +Vector2d RenderText::GetAlignmentOffset(size_t line_number) { + // TODO(ckocagil): Enable |lines_| usage in other platforms. +#if defined(OS_WIN) + DCHECK_LT(line_number, lines_.size()); +#endif Vector2d offset; if (horizontal_alignment_ != ALIGN_LEFT) { - offset.set_x(display_rect().width() - GetContentWidth()); +#if defined(OS_WIN) + const int width = lines_[line_number].size.width() + + (cursor_enabled_ ? 1 : 0); +#else + const int width = GetContentWidth(); +#endif + offset.set_x(display_rect().width() - width); if (horizontal_alignment_ == ALIGN_CENTER) offset.set_x(offset.x() / 2); } @@ -875,14 +973,13 @@ Vector2d RenderText::GetAlignmentOffset() { } void RenderText::ApplyFadeEffects(internal::SkiaTextRenderer* renderer) { - if (!fade_head() && !fade_tail()) + if (multiline() || (!fade_head() && !fade_tail())) return; - const int text_width = GetStringSize().width(); const int display_width = display_rect().width(); // If the text fits as-is, no need to fade. - if (text_width <= display_width) + if (GetStringSize().width() <= display_width) return; int gradient_width = CalculateFadeGradientWidth(GetPrimaryFont(), @@ -914,7 +1011,7 @@ void RenderText::ApplyFadeEffects(internal::SkiaTextRenderer* renderer) { } Rect text_rect = display_rect(); - text_rect.Inset(GetAlignmentOffset().x(), 0, 0, 0); + text_rect.Inset(GetAlignmentOffset(0).x(), 0, 0, 0); // TODO(msw): Use the actual text colors corresponding to each faded part. skia::RefPtr<SkShader> shader = CreateFadeShader( @@ -929,29 +1026,30 @@ void RenderText::ApplyTextShadows(internal::SkiaTextRenderer* renderer) { } // static -bool RenderText::RangeContainsCaret(const ui::Range& range, +bool RenderText::RangeContainsCaret(const Range& range, size_t caret_pos, LogicalCursorDirection caret_affinity) { // NB: exploits unsigned wraparound (WG14/N1124 section 6.2.5 paragraph 9). size_t adjacent = (caret_affinity == CURSOR_BACKWARD) ? caret_pos - 1 : caret_pos + 1; - return range.Contains(ui::Range(caret_pos, adjacent)); + return range.Contains(Range(caret_pos, adjacent)); } void RenderText::MoveCursorTo(size_t position, bool select) { size_t cursor = std::min(position, text().length()); if (IsCursorablePosition(cursor)) SetSelectionModel(SelectionModel( - ui::Range(select ? selection().start() : cursor, cursor), + Range(select ? selection().start() : cursor, cursor), (cursor == 0) ? CURSOR_FORWARD : CURSOR_BACKWARD)); } void RenderText::UpdateLayoutText() { layout_text_.clear(); + line_breaks_.SetMax(0); if (obscured_) { size_t obscured_text_length = - static_cast<size_t>(ui::UTF16IndexToOffset(text_, 0, text_.length())); + static_cast<size_t>(gfx::UTF16IndexToOffset(text_, 0, text_.length())); layout_text_.assign(obscured_text_length, kPasswordReplacementChar); if (obscured_reveal_index_ >= 0 && @@ -965,7 +1063,7 @@ void RenderText::UpdateLayoutText() { // Gets the index in |layout_text_| to be replaced. const size_t cp_start = - static_cast<size_t>(ui::UTF16IndexToOffset(text_, 0, start)); + static_cast<size_t>(gfx::UTF16IndexToOffset(text_, 0, start)); if (layout_text_.length() > cp_start) layout_text_.replace(cp_start, 1, text_.substr(start, end - start)); } @@ -976,7 +1074,7 @@ void RenderText::UpdateLayoutText() { // Truncate the text at a valid character break and append an ellipsis. icu::StringCharacterIterator iter(text.c_str()); iter.setIndex32(truncate_length_ - 1); - layout_text_.assign(text.substr(0, iter.getIndex()) + ui::kEllipsisUTF16); + layout_text_.assign(text.substr(0, iter.getIndex()) + gfx::kEllipsisUTF16); } } @@ -984,6 +1082,8 @@ void RenderText::UpdateCachedBoundsAndOffset() { if (cached_bounds_and_offset_valid_) return; + // TODO(ckocagil): Add support for scrolling multiline text. + // First, set the valid flag true to calculate the current cursor bounds using // the stale |display_offset_|. Applying |delta_offset| at the end of this // function will set |cursor_bounds_| and |display_offset_| to correct values. diff --git a/chromium/ui/gfx/render_text.h b/chromium/ui/gfx/render_text.h index 34277400b73..598f4e1d181 100644 --- a/chromium/ui/gfx/render_text.h +++ b/chromium/ui/gfx/render_text.h @@ -18,10 +18,10 @@ #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkPaint.h" #include "third_party/skia/include/core/SkRect.h" -#include "ui/base/range/range.h" #include "ui/gfx/break_list.h" #include "ui/gfx/font_list.h" #include "ui/gfx/point.h" +#include "ui/gfx/range/range.h" #include "ui/gfx/rect.h" #include "ui/gfx/selection_model.h" #include "ui/gfx/shadow_value.h" @@ -96,7 +96,7 @@ class StyleIterator { bool style(TextStyle s) const { return style_[s]->second; } // Get the intersecting range of the current iterator set. - ui::Range GetRange() const; + Range GetRange() const; // Update the iterator to point to colors and styles applicable at |position|. void UpdatePosition(size_t position); @@ -111,6 +111,40 @@ class StyleIterator { DISALLOW_COPY_AND_ASSIGN(StyleIterator); }; +// Line segments are slices of the layout text to be rendered on a single line. +struct LineSegment { + LineSegment(); + ~LineSegment(); + + // X coordinates of this line segment in text space. + Range x_range; + + // The character range this segment corresponds to. + Range char_range; + + // Index of the text run that generated this segment. + size_t run; +}; + +// A line of layout text, comprised of a line segment list and some metrics. +struct Line { + Line(); + ~Line(); + + // Segments that make up this line in visual order. + std::vector<LineSegment> segments; + + // A line size is the sum of segment widths and the maximum of segment + // heights. + Size size; + + // Sum of preceding lines' heights. + int preceding_heights; + + // Maximum baseline of all segments on this line. + int baseline; +}; + } // namespace internal // RenderText represents an abstract model of styled text and its corresponding @@ -186,6 +220,11 @@ class UI_EXPORT RenderText { // cleared when SetText or SetObscured is called. void SetObscuredRevealIndex(int index); + // TODO(ckocagil): Multiline text rendering is currently only supported on + // Windows. Support other platforms. + bool multiline() const { return multiline_; } + void SetMultiline(bool multiline); + // Set the maximum length of the displayed layout text, not the actual text. // A |length| of 0 forgoes a hard limit, but does not guarantee proper // functionality of very long strings. Applies to subsequent SetText calls. @@ -207,7 +246,7 @@ class UI_EXPORT RenderText { const SelectionModel& selection_model() const { return selection_model_; } - const ui::Range& selection() const { return selection_model_.selection(); } + const Range& selection() const { return selection_model_.selection(); } size_t cursor_position() const { return selection_model_.caret_pos(); } void SetCursorPosition(size_t position); @@ -236,7 +275,7 @@ class UI_EXPORT RenderText { // to be the text length. // If the |range| start or end is not a cursorable position (not on grapheme // boundary), it is a NO-OP and returns false. Otherwise, returns true. - bool SelectRange(const ui::Range& range); + bool SelectRange(const Range& range); // Returns true if the local point is over selected text. bool IsPointInSelection(const Point& point); @@ -254,19 +293,19 @@ class UI_EXPORT RenderText { // boundaries. void SelectWord(); - const ui::Range& GetCompositionRange() const; - void SetCompositionRange(const ui::Range& composition_range); + const Range& GetCompositionRange() const; + void SetCompositionRange(const Range& composition_range); // Set the text color over the entire text or a logical character range. // The |range| should be valid, non-reversed, and within [0, text().length()]. void SetColor(SkColor value); - void ApplyColor(SkColor value, const ui::Range& range); + void ApplyColor(SkColor value, const Range& range); // Set various text styles over the entire text or a logical character range. // The respective |style| is applied if |value| is true, or removed if false. // The |range| should be valid, non-reversed, and within [0, text().length()]. void SetStyle(TextStyle style, bool value); - void ApplyStyle(TextStyle style, bool value, const ui::Range& range); + void ApplyStyle(TextStyle style, bool value, const Range& range); // Returns whether this style is enabled consistently across the entire // RenderText. @@ -281,14 +320,14 @@ class UI_EXPORT RenderText { // |GetTextDirection()|, not the direction of a particular run. VisualCursorDirection GetVisualDirectionOfLogicalEnd(); - // Returns the size in pixels of the entire string. For the height, this will - // return the maximum height among the different fonts in the text runs. - // Note that this returns the raw size of the string, which does not include - // the margin area of text shadows. + // Returns the size required to display the current string (which is the + // wrapped size in multiline mode). Note that this returns the raw size of the + // string, which does not include the cursor or the margin area of text + // shadows. virtual Size GetStringSize() = 0; - // Returns the width of content, which reserves room for the cursor if - // |cursor_enabled_| is true. + // Returns the width of the content (which is the wrapped width in multiline + // mode). Reserves room for the cursor if |cursor_enabled_| is true. int GetContentWidth(); // Returns the common baseline of the text. The returned value is the vertical @@ -335,7 +374,7 @@ class UI_EXPORT RenderText { // Sets shadows to drawn with text. void SetTextShadows(const ShadowValues& shadows); - typedef std::pair<Font, ui::Range> FontSpan; + typedef std::pair<Font, Range> FontSpan; // For testing purposes, returns which fonts were chosen for which parts of // the text by returning a vector of Font and Range pairs, where each range // specifies the character range for which the corresponding font has been @@ -348,6 +387,9 @@ class UI_EXPORT RenderText { const BreakList<SkColor>& colors() const { return colors_; } const std::vector<BreakList<bool> >& styles() const { return styles_; } + const std::vector<internal::Line>& lines() const { return lines_; } + void set_lines(std::vector<internal::Line>* lines) { lines_.swap(*lines); } + const Vector2d& GetUpdatedDisplayOffset(); void set_cached_bounds_and_offset_valid(bool valid) { @@ -383,7 +425,7 @@ class UI_EXPORT RenderText { // of the glyph starting at |index|. If the glyph is RTL then the returned // Range will have is_reversed() true. (This does not return a Rect because a // Rect can't have a negative width.) - virtual ui::Range GetGlyphBounds(size_t index) = 0; + virtual Range GetGlyphBounds(size_t index) = 0; // Get the visual bounds containing the logical substring within the |range|. // If |range| is empty, the result is empty. These bounds could be visually @@ -391,7 +433,7 @@ class UI_EXPORT RenderText { // These bounds are in local coordinates, but may be outside the visible // region if the text is longer than the textfield. Subsequent text, cursor, // or bounds changes may invalidate returned values. - virtual std::vector<Rect> GetSubstringBounds(const ui::Range& range) = 0; + virtual std::vector<Rect> GetSubstringBounds(const Range& range) = 0; // Convert between indices into |text_| and indices into |obscured_text_|, // which differ when the text is obscured. Regardless of whether or not the @@ -406,7 +448,7 @@ class UI_EXPORT RenderText { // Reset the layout to be invalid. virtual void ResetLayout() = 0; - // Ensure the text is laid out. + // Ensure the text is laid out, lines are computed, and |lines_| is valid. virtual void EnsureLayout() = 0; // Draw the text. @@ -415,22 +457,29 @@ class UI_EXPORT RenderText { // Returns the text used for layout, which may be obscured or truncated. const base::string16& GetLayoutText() const; + // Returns layout text positions that are suitable for breaking lines. + const BreakList<size_t>& GetLineBreaks(); + // Apply (and undo) temporary composition underlines and selection colors. void ApplyCompositionAndSelectionStyles(); void UndoCompositionAndSelectionStyles(); - // Returns the text offset from the origin after applying text alignment and - // display offset. - Vector2d GetTextOffset(); + // Returns the line offset from the origin after applying the text alignment + // and the display offset. + Vector2d GetLineOffset(size_t line_number); - // Convert points from the text space to the view space and back. - // Handles the display area, display offset, and the application LTR/RTL mode. + // Convert points from the text space to the view space and back. Handles the + // display area, display offset, application LTR/RTL mode and multiline. Point ToTextPoint(const Point& point); Point ToViewPoint(const Point& point); - // Returns the text offset from the origin, taking into account text alignment + // Convert a text space x-coordinate range to corresponding rects in view + // space. + std::vector<Rect> TextBoundsToViewBounds(const Range& x); + + // Returns the line offset from the origin, accounting for text alignment // only. - Vector2d GetAlignmentOffset(); + Vector2d GetAlignmentOffset(size_t line_number); // Applies fade effects to |renderer|. void ApplyFadeEffects(internal::SkiaTextRenderer* renderer); @@ -440,7 +489,7 @@ class UI_EXPORT RenderText { // A convenience function to check whether the glyph attached to the caret // is within the given range. - static bool RangeContainsCaret(const ui::Range& range, + static bool RangeContainsCaret(const Range& range, size_t caret_pos, LogicalCursorDirection caret_affinity); @@ -457,6 +506,9 @@ class UI_EXPORT RenderText { FRIEND_TEST_ALL_PREFIXES(RenderTextTest, EdgeSelectionModels); FRIEND_TEST_ALL_PREFIXES(RenderTextTest, GetTextOffset); FRIEND_TEST_ALL_PREFIXES(RenderTextTest, GetTextOffsetHorizontalDefaultInRTL); + FRIEND_TEST_ALL_PREFIXES(RenderTextTest, Multiline_MinWidth); + FRIEND_TEST_ALL_PREFIXES(RenderTextTest, Multiline_NormalWidth); + FRIEND_TEST_ALL_PREFIXES(RenderTextTest, Multiline_SufficientWidth); // Set the cursor to |position|, with the caret trailing the previous // grapheme, or if there is no previous grapheme, leading the cursor position. @@ -523,7 +575,7 @@ class UI_EXPORT RenderText { bool focused_; // Composition text range. - ui::Range composition_range_; + Range composition_range_; // Color and style breaks, used to color and stylize ranges of text. // BreakList positions are stored with text indices, not layout indices. @@ -547,6 +599,10 @@ class UI_EXPORT RenderText { // The obscured and/or truncated text that will be displayed. base::string16 layout_text_; + // Whether the text should be broken into multiple lines. Uses the width of + // |display_rect_| as the width cap. + bool multiline_; + // Fade text head and/or tail, if text doesn't fit into |display_rect_|. bool fade_head_; bool fade_tail_; @@ -574,6 +630,13 @@ class UI_EXPORT RenderText { // Text shadows to be drawn. ShadowValues text_shadows_; + // A list of valid layout text line break positions. + BreakList<size_t> line_breaks_; + + // Lines computed by EnsureLayout. These should be invalidated with + // ResetLayout and on |display_rect_| changes. + std::vector<internal::Line> lines_; + DISALLOW_COPY_AND_ASSIGN(RenderText); }; diff --git a/chromium/ui/gfx/render_text_linux.cc b/chromium/ui/gfx/render_text_linux.cc index 0178cf8368b..4b7b93474ae 100644 --- a/chromium/ui/gfx/render_text_linux.cc +++ b/chromium/ui/gfx/render_text_linux.cc @@ -12,11 +12,11 @@ #include "base/i18n/break_iterator.h" #include "base/logging.h" #include "third_party/skia/include/core/SkTypeface.h" -#include "ui/base/text/utf16_indexing.h" #include "ui/gfx/canvas.h" #include "ui/gfx/font.h" #include "ui/gfx/font_render_params_linux.h" #include "ui/gfx/pango_util.h" +#include "ui/gfx/utf16_indexing.h" namespace gfx { @@ -40,9 +40,9 @@ bool IsForwardMotion(VisualCursorDirection direction, const PangoItem* item) { } // Checks whether |range| contains |index|. This is not the same as calling -// |range.Contains(ui::Range(index))| - as that would return true when +// |range.Contains(gfx::Range(index))| - as that would return true when // |index| == |range.end()|. -bool IndexInRange(const ui::Range& range, size_t index) { +bool IndexInRange(const Range& range, size_t index) { return index >= range.start() && index < range.end(); } @@ -137,7 +137,7 @@ std::vector<RenderText::FontSpan> RenderTextLinux::GetFontSpansForTesting() { PangoItem* item = reinterpret_cast<PangoLayoutRun*>(it->data)->item; const int start = LayoutIndexToTextIndex(item->offset); const int end = LayoutIndexToTextIndex(item->offset + item->length); - const ui::Range range(start, end); + const Range range(start, end); ScopedPangoFontDescription desc(pango_font_describe(item->analysis.font)); spans.push_back(RenderText::FontSpan(Font(desc.get()), range)); @@ -214,14 +214,14 @@ SelectionModel RenderTextLinux::AdjacentWordSelectionModel( return cur; } -ui::Range RenderTextLinux::GetGlyphBounds(size_t index) { +Range RenderTextLinux::GetGlyphBounds(size_t index) { PangoRectangle pos; pango_layout_index_to_pos(layout_, TextIndexToLayoutIndex(index), &pos); // TODO(derat): Support fractional ranges for subpixel positioning? - return ui::Range(PANGO_PIXELS(pos.x), PANGO_PIXELS(pos.x + pos.width)); + return Range(PANGO_PIXELS(pos.x), PANGO_PIXELS(pos.x + pos.width)); } -std::vector<Rect> RenderTextLinux::GetSubstringBounds(const ui::Range& range) { +std::vector<Rect> RenderTextLinux::GetSubstringBounds(const Range& range) { DCHECK_LE(range.GetMax(), text().length()); if (range.is_empty()) return std::vector<Rect>(); @@ -252,7 +252,7 @@ std::vector<Rect> RenderTextLinux::GetSubstringBounds(const ui::Range& range) { size_t RenderTextLinux::TextIndexToLayoutIndex(size_t index) const { DCHECK(layout_); - ptrdiff_t offset = ui::UTF16IndexToOffset(text(), 0, index); + ptrdiff_t offset = gfx::UTF16IndexToOffset(text(), 0, index); // Clamp layout indices to the length of the text actually used for layout. offset = std::min<size_t>(offset, g_utf8_strlen(layout_text_, -1)); const char* layout_pointer = g_utf8_offset_to_pointer(layout_text_, offset); @@ -263,7 +263,7 @@ size_t RenderTextLinux::LayoutIndexToTextIndex(size_t index) const { DCHECK(layout_); const char* layout_pointer = layout_text_ + index; const long offset = g_utf8_pointer_to_offset(layout_text_, layout_pointer); - return ui::UTF16OffsetToIndex(text(), 0, offset); + return gfx::UTF16OffsetToIndex(text(), 0, offset); } bool RenderTextLinux::IsCursorablePosition(size_t position) { @@ -271,11 +271,11 @@ bool RenderTextLinux::IsCursorablePosition(size_t position) { return true; if (position >= text().length()) return position == text().length(); - if (!ui::IsValidCodePointIndex(text(), position)) + if (!gfx::IsValidCodePointIndex(text(), position)) return false; EnsureLayout(); - ptrdiff_t offset = ui::UTF16IndexToOffset(text(), 0, position); + ptrdiff_t offset = gfx::UTF16IndexToOffset(text(), 0, position); // Check that the index corresponds with a valid text code point, that it is // marked as a legitimate cursor position by Pango, and that it is not // truncated from layout text (its glyph is shown on screen). @@ -287,6 +287,7 @@ void RenderTextLinux::ResetLayout() { // set_cached_bounds_and_offset_valid(false) is done in RenderText for every // operation that triggers ResetLayout(). if (layout_) { + // TODO(msw): Keep |layout_| across text changes, etc.; it can be re-used. g_object_unref(layout_); layout_ = NULL; } @@ -306,9 +307,12 @@ void RenderTextLinux::EnsureLayout() { if (layout_ == NULL) { cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0); + CHECK_EQ(CAIRO_STATUS_SUCCESS, cairo_surface_status(surface)); cairo_t* cr = cairo_create(surface); + CHECK_EQ(CAIRO_STATUS_SUCCESS, cairo_status(cr)); layout_ = pango_cairo_create_layout(cr); + CHECK_NE(static_cast<PangoLayout*>(NULL), layout_); cairo_destroy(cr); cairo_surface_destroy(surface); @@ -331,6 +335,7 @@ void RenderTextLinux::EnsureLayout() { SetupPangoAttributes(layout_); current_line_ = pango_layout_get_line_readonly(layout_, 0); + CHECK_NE(static_cast<PangoLayoutLine*>(NULL), current_line_); pango_layout_line_ref(current_line_); pango_layout_get_log_attrs(layout_, &log_attrs_, &num_log_attrs_); @@ -376,7 +381,7 @@ void RenderTextLinux::DrawVisualText(Canvas* canvas) { DCHECK(layout_); // Skia will draw glyphs with respect to the baseline. - Vector2d offset(GetTextOffset() + Vector2d(0, GetBaseline())); + Vector2d offset(GetLineOffset(0) + Vector2d(0, GetBaseline())); SkScalar x = SkIntToScalar(offset.x()); SkScalar y = SkIntToScalar(offset.y()); @@ -428,7 +433,7 @@ void RenderTextLinux::DrawVisualText(Canvas* canvas) { // Track the current style and its text (not layout) index range. style.UpdatePosition(GetGlyphTextIndex(run, style_start_glyph_index)); - ui::Range style_range = style.GetRange(); + Range style_range = style.GetRange(); do { const PangoGlyphInfo& glyph = run->glyphs->glyphs[glyph_index]; @@ -478,7 +483,7 @@ GSList* RenderTextLinux::GetRunContainingCaret( GSList* run = current_line_->runs; while (run) { PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item; - ui::Range item_range(item->offset, item->offset + item->length); + Range item_range(item->offset, item->offset + item->length); if (RangeContainsCaret(item_range, position, affinity)) return run; run = run->next; diff --git a/chromium/ui/gfx/render_text_linux.h b/chromium/ui/gfx/render_text_linux.h index a2b1e665ae7..1500fc0adef 100644 --- a/chromium/ui/gfx/render_text_linux.h +++ b/chromium/ui/gfx/render_text_linux.h @@ -32,8 +32,8 @@ class RenderTextLinux : public RenderText { virtual SelectionModel AdjacentWordSelectionModel( const SelectionModel& selection, VisualCursorDirection direction) OVERRIDE; - virtual ui::Range GetGlyphBounds(size_t index) OVERRIDE; - virtual std::vector<Rect> GetSubstringBounds(const ui::Range& range) OVERRIDE; + virtual Range GetGlyphBounds(size_t index) OVERRIDE; + virtual std::vector<Rect> GetSubstringBounds(const Range& range) OVERRIDE; virtual size_t TextIndexToLayoutIndex(size_t index) const OVERRIDE; virtual size_t LayoutIndexToTextIndex(size_t index) const OVERRIDE; virtual bool IsCursorablePosition(size_t position) OVERRIDE; diff --git a/chromium/ui/gfx/render_text_mac.cc b/chromium/ui/gfx/render_text_mac.cc index c56c62638f7..2fcea01b157 100644 --- a/chromium/ui/gfx/render_text_mac.cc +++ b/chromium/ui/gfx/render_text_mac.cc @@ -47,8 +47,7 @@ std::vector<RenderText::FontSpan> RenderTextMac::GetFontSpansForTesting() { for (size_t i = 0; i < runs_.size(); ++i) { gfx::Font font(runs_[i].font_name, runs_[i].text_size); const CFRange cf_range = CTRunGetStringRange(runs_[i].ct_run); - const ui::Range range(cf_range.location, - cf_range.location + cf_range.length); + const Range range(cf_range.location, cf_range.location + cf_range.length); spans.push_back(RenderText::FontSpan(font, range)); } @@ -69,12 +68,12 @@ SelectionModel RenderTextMac::AdjacentWordSelectionModel( return SelectionModel(); } -ui::Range RenderTextMac::GetGlyphBounds(size_t index) { +Range RenderTextMac::GetGlyphBounds(size_t index) { // TODO(asvitkine): Implement this. http://crbug.com/131618 - return ui::Range(); + return Range(); } -std::vector<Rect> RenderTextMac::GetSubstringBounds(const ui::Range& range) { +std::vector<Rect> RenderTextMac::GetSubstringBounds(const Range& range) { // TODO(asvitkine): Implement this. http://crbug.com/131618 return std::vector<Rect>(); } @@ -150,7 +149,7 @@ void RenderTextMac::EnsureLayout() { CGFloat font_list_baseline = font_list().GetBaseline(); ascent = std::max(ascent, font_list_baseline); descent = std::max(descent, font_list_height - font_list_baseline); - string_size_ = Size(width, ascent + descent + leading); + string_size_ = Size(std::ceil(width), ascent + descent + leading); common_baseline_ = ascent; } @@ -249,9 +248,9 @@ void RenderTextMac::ComputeRuns() { CFArrayRef ct_runs = CTLineGetGlyphRuns(line_); const CFIndex ct_runs_count = CFArrayGetCount(ct_runs); - // TODO(asvitkine): Don't use GetTextOffset() until draw time, since it may be + // TODO(asvitkine): Don't use GetLineOffset() until draw time, since it may be // updated based on alignment changes without resetting the layout. - gfx::Vector2d text_offset = GetTextOffset(); + gfx::Vector2d text_offset = GetLineOffset(0); // Skia will draw glyphs with respect to the baseline. text_offset += gfx::Vector2d(0, common_baseline_); diff --git a/chromium/ui/gfx/render_text_mac.h b/chromium/ui/gfx/render_text_mac.h index 345fef0e98d..be5f12865c0 100644 --- a/chromium/ui/gfx/render_text_mac.h +++ b/chromium/ui/gfx/render_text_mac.h @@ -39,8 +39,8 @@ class RenderTextMac : public RenderText { virtual SelectionModel AdjacentWordSelectionModel( const SelectionModel& selection, VisualCursorDirection direction) OVERRIDE; - virtual ui::Range GetGlyphBounds(size_t index) OVERRIDE; - virtual std::vector<Rect> GetSubstringBounds(const ui::Range& range) OVERRIDE; + virtual Range GetGlyphBounds(size_t index) OVERRIDE; + virtual std::vector<Rect> GetSubstringBounds(const Range& range) OVERRIDE; virtual size_t TextIndexToLayoutIndex(size_t index) const OVERRIDE; virtual size_t LayoutIndexToTextIndex(size_t index) const OVERRIDE; virtual bool IsCursorablePosition(size_t position) OVERRIDE; diff --git a/chromium/ui/gfx/render_text_unittest.cc b/chromium/ui/gfx/render_text_unittest.cc index 263ef92d815..52cb8344b37 100644 --- a/chromium/ui/gfx/render_text_unittest.cc +++ b/chromium/ui/gfx/render_text_unittest.cc @@ -6,6 +6,7 @@ #include <algorithm> +#include "base/format_macros.h" #include "base/memory/scoped_ptr.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" @@ -40,9 +41,9 @@ const wchar_t kRtlLtr[] = L"\x5d0\x5d1" L"a"; const wchar_t kRtlLtrRtl[] = L"\x5d0" L"a" L"\x5d1"; // Checks whether |range| contains |index|. This is not the same as calling -// |range.Contains(ui::Range(index))| - as that would return true when +// |range.Contains(gfx::Range(index))| - as that would return true when // |index| == |range.end()|. -bool IndexInRange(const ui::Range& range, size_t index) { +bool IndexInRange(const Range& range, size_t index) { return index >= range.start() && index < range.end(); } @@ -124,8 +125,8 @@ TEST_F(RenderTextTest, ApplyColorAndStyle) { render_text->SetText(ASCIIToUTF16("012345678")); // Apply a ranged color and style and check the resulting breaks. - render_text->ApplyColor(SK_ColorRED, ui::Range(1, 4)); - render_text->ApplyStyle(BOLD, true, ui::Range(2, 5)); + render_text->ApplyColor(SK_ColorRED, Range(1, 4)); + render_text->ApplyStyle(BOLD, true, Range(2, 5)); std::vector<std::pair<size_t, SkColor> > expected_color; expected_color.push_back(std::pair<size_t, SkColor>(0, SK_ColorBLACK)); expected_color.push_back(std::pair<size_t, SkColor>(1, SK_ColorRED)); @@ -146,8 +147,8 @@ TEST_F(RenderTextTest, ApplyColorAndStyle) { // Apply a color and style over the text end and check the resulting breaks. // (INT_MAX should be used instead of the text length for the range end) const size_t text_length = render_text->text().length(); - render_text->ApplyColor(SK_ColorRED, ui::Range(0, text_length)); - render_text->ApplyStyle(BOLD, true, ui::Range(2, text_length)); + render_text->ApplyColor(SK_ColorRED, Range(0, text_length)); + render_text->ApplyStyle(BOLD, true, Range(2, text_length)); std::vector<std::pair<size_t, SkColor> > expected_color_end; expected_color_end.push_back(std::pair<size_t, SkColor>(0, SK_ColorRED)); EXPECT_TRUE(render_text->colors().EqualsForTesting(expected_color_end)); @@ -157,9 +158,9 @@ TEST_F(RenderTextTest, ApplyColorAndStyle) { EXPECT_TRUE(render_text->styles()[BOLD].EqualsForTesting(expected_style_end)); // Ensure ranged values adjust to accommodate text length changes. - render_text->ApplyStyle(ITALIC, true, ui::Range(0, 2)); - render_text->ApplyStyle(ITALIC, true, ui::Range(3, 6)); - render_text->ApplyStyle(ITALIC, true, ui::Range(7, text_length)); + render_text->ApplyStyle(ITALIC, true, Range(0, 2)); + render_text->ApplyStyle(ITALIC, true, Range(3, 6)); + render_text->ApplyStyle(ITALIC, true, Range(7, text_length)); std::vector<std::pair<size_t, bool> > expected_italic; expected_italic.push_back(std::pair<size_t, bool>(0, true)); expected_italic.push_back(std::pair<size_t, bool>(2, false)); @@ -187,8 +188,8 @@ TEST_F(RenderTextTest, PangoAttributes) { render_text->SetText(ASCIIToUTF16("012345678")); // Apply ranged BOLD/ITALIC styles and check the resulting Pango attributes. - render_text->ApplyStyle(BOLD, true, ui::Range(2, 4)); - render_text->ApplyStyle(ITALIC, true, ui::Range(1, 3)); + render_text->ApplyStyle(BOLD, true, Range(2, 4)); + render_text->ApplyStyle(ITALIC, true, Range(1, 3)); struct { int start; @@ -239,22 +240,22 @@ void TestVisualCursorMotionInObscuredField(RenderText* render_text, render_text->SetText(text); int len = text.length(); render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, select); - EXPECT_EQ(SelectionModel(ui::Range(select ? 0 : len, len), CURSOR_FORWARD), + EXPECT_EQ(SelectionModel(Range(select ? 0 : len, len), CURSOR_FORWARD), render_text->selection_model()); render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, select); EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model()); for (int j = 1; j <= len; ++j) { render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, select); - EXPECT_EQ(SelectionModel(ui::Range(select ? 0 : j, j), CURSOR_BACKWARD), + EXPECT_EQ(SelectionModel(Range(select ? 0 : j, j), CURSOR_BACKWARD), render_text->selection_model()); } for (int j = len - 1; j >= 0; --j) { render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, select); - EXPECT_EQ(SelectionModel(ui::Range(select ? 0 : j, j), CURSOR_FORWARD), + EXPECT_EQ(SelectionModel(Range(select ? 0 : j, j), CURSOR_FORWARD), render_text->selection_model()); } render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, select); - EXPECT_EQ(SelectionModel(ui::Range(select ? 0 : len, len), CURSOR_FORWARD), + EXPECT_EQ(SelectionModel(Range(select ? 0 : len, len), CURSOR_FORWARD), render_text->selection_model()); render_text->MoveCursor(WORD_BREAK, CURSOR_LEFT, select); EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model()); @@ -878,8 +879,8 @@ TEST_F(RenderTextTest, SelectAll) { // Ensure that SelectAll respects the |reversed| argument regardless of // application locale and text content directionality. scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); - const SelectionModel expected_reversed(ui::Range(3, 0), CURSOR_FORWARD); - const SelectionModel expected_forwards(ui::Range(0, 3), CURSOR_BACKWARD); + const SelectionModel expected_reversed(Range(3, 0), CURSOR_FORWARD); + const SelectionModel expected_forwards(Range(0, 3), CURSOR_BACKWARD); const bool was_rtl = base::i18n::IsRTL(); for (size_t i = 0; i < 2; ++i) { @@ -906,39 +907,39 @@ TEST_F(RenderTextTest, SelectAll) { render_text->SetText(WideToUTF16(L"abc\x05d0\x05d1\x05d2")); // Left arrow on select ranging (6, 4). render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false); - EXPECT_EQ(ui::Range(6), render_text->selection()); + EXPECT_EQ(Range(6), render_text->selection()); render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false); - EXPECT_EQ(ui::Range(4), render_text->selection()); + EXPECT_EQ(Range(4), render_text->selection()); render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false); - EXPECT_EQ(ui::Range(5), render_text->selection()); + EXPECT_EQ(Range(5), render_text->selection()); render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false); - EXPECT_EQ(ui::Range(6), render_text->selection()); + EXPECT_EQ(Range(6), render_text->selection()); render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, true); - EXPECT_EQ(ui::Range(6, 5), render_text->selection()); + EXPECT_EQ(Range(6, 5), render_text->selection()); render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, true); - EXPECT_EQ(ui::Range(6, 4), render_text->selection()); + EXPECT_EQ(Range(6, 4), render_text->selection()); render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false); - EXPECT_EQ(ui::Range(6), render_text->selection()); + EXPECT_EQ(Range(6), render_text->selection()); // Right arrow on select ranging (4, 6). render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false); - EXPECT_EQ(ui::Range(0), render_text->selection()); + EXPECT_EQ(Range(0), render_text->selection()); render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false); - EXPECT_EQ(ui::Range(1), render_text->selection()); + EXPECT_EQ(Range(1), render_text->selection()); render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false); - EXPECT_EQ(ui::Range(2), render_text->selection()); + EXPECT_EQ(Range(2), render_text->selection()); render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false); - EXPECT_EQ(ui::Range(3), render_text->selection()); + EXPECT_EQ(Range(3), render_text->selection()); render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false); - EXPECT_EQ(ui::Range(5), render_text->selection()); + EXPECT_EQ(Range(5), render_text->selection()); render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false); - EXPECT_EQ(ui::Range(4), render_text->selection()); + EXPECT_EQ(Range(4), render_text->selection()); render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, true); - EXPECT_EQ(ui::Range(4, 5), render_text->selection()); + EXPECT_EQ(Range(4, 5), render_text->selection()); render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, true); - EXPECT_EQ(ui::Range(4, 6), render_text->selection()); + EXPECT_EQ(Range(4, 6), render_text->selection()); render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false); - EXPECT_EQ(ui::Range(4), render_text->selection()); + EXPECT_EQ(Range(4), render_text->selection()); } #endif // !defined(OS_MACOSX) @@ -1225,7 +1226,7 @@ TEST_F(RenderTextTest, StringSizeBoldWidth) { EXPECT_GT(bold_width, plain_width); // Now, apply a plain style over the first word only. - render_text->ApplyStyle(BOLD, false, ui::Range(0, 5)); + render_text->ApplyStyle(BOLD, false, Range(0, 5)); const int plain_bold_width = render_text->GetStringSize().width(); EXPECT_GT(plain_bold_width, plain_width); EXPECT_LT(plain_bold_width, bold_width); @@ -1294,7 +1295,7 @@ TEST_F(RenderTextTest, GetTextOffset) { Rect display_rect(font_size); render_text->SetDisplayRect(display_rect); - Vector2d offset = render_text->GetTextOffset(); + Vector2d offset = render_text->GetLineOffset(0); EXPECT_TRUE(offset.IsZero()); // Set display area's size greater than font size. @@ -1303,30 +1304,30 @@ TEST_F(RenderTextTest, GetTextOffset) { render_text->SetDisplayRect(display_rect); // Check the default horizontal and vertical alignment. - offset = render_text->GetTextOffset(); + offset = render_text->GetLineOffset(0); EXPECT_EQ(kEnlargement / 2, offset.y()); EXPECT_EQ(0, offset.x()); // Check explicitly setting the horizontal alignment. render_text->SetHorizontalAlignment(ALIGN_LEFT); - offset = render_text->GetTextOffset(); + offset = render_text->GetLineOffset(0); EXPECT_EQ(0, offset.x()); render_text->SetHorizontalAlignment(ALIGN_CENTER); - offset = render_text->GetTextOffset(); + offset = render_text->GetLineOffset(0); EXPECT_EQ(kEnlargement / 2, offset.x()); render_text->SetHorizontalAlignment(ALIGN_RIGHT); - offset = render_text->GetTextOffset(); + offset = render_text->GetLineOffset(0); EXPECT_EQ(kEnlargement, offset.x()); // Check explicitly setting the vertical alignment. render_text->SetVerticalAlignment(ALIGN_TOP); - offset = render_text->GetTextOffset(); + offset = render_text->GetLineOffset(0); EXPECT_EQ(0, offset.y()); render_text->SetVerticalAlignment(ALIGN_VCENTER); - offset = render_text->GetTextOffset(); + offset = render_text->GetLineOffset(0); EXPECT_EQ(kEnlargement / 2, offset.y()); render_text->SetVerticalAlignment(ALIGN_BOTTOM); - offset = render_text->GetTextOffset(); + offset = render_text->GetLineOffset(0); EXPECT_EQ(kEnlargement, offset.y()); SetRTL(was_rtl); @@ -1334,7 +1335,7 @@ TEST_F(RenderTextTest, GetTextOffset) { TEST_F(RenderTextTest, GetTextOffsetHorizontalDefaultInRTL) { // This only checks the default horizontal alignment in RTL mode; all other - // GetTextOffset() attributes are checked by the test above. + // GetLineOffset(0) attributes are checked by the test above. const bool was_rtl = base::i18n::IsRTL(); SetRTL(true); scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); @@ -1345,7 +1346,7 @@ TEST_F(RenderTextTest, GetTextOffsetHorizontalDefaultInRTL) { render_text->GetStringSize().height()); Rect display_rect(font_size); render_text->SetDisplayRect(display_rect); - Vector2d offset = render_text->GetTextOffset(); + Vector2d offset = render_text->GetLineOffset(0); EXPECT_EQ(kEnlargement, offset.x()); SetRTL(was_rtl); } @@ -1464,7 +1465,7 @@ TEST_F(RenderTextTest, SelectWord) { for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { render_text->SetCursorPosition(cases[i].cursor); render_text->SelectWord(); - EXPECT_EQ(ui::Range(cases[i].selection_start, cases[i].selection_end), + EXPECT_EQ(Range(cases[i].selection_start, cases[i].selection_end), render_text->selection()); } } @@ -1497,13 +1498,13 @@ TEST_F(RenderTextTest, SelectMultipleWords) { scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); render_text->SetText(ASCIIToUTF16(kTestURL)); - render_text->SelectRange(ui::Range(16, 20)); + render_text->SelectRange(Range(16, 20)); render_text->SelectWord(); EXPECT_EQ(ASCIIToUTF16("google.com"), GetSelectedText(render_text.get())); EXPECT_FALSE(render_text->selection().is_reversed()); // SelectWord should preserve the selection direction. - render_text->SelectRange(ui::Range(20, 16)); + render_text->SelectRange(Range(20, 16)); render_text->SelectWord(); EXPECT_EQ(ASCIIToUTF16("google.com"), GetSelectedText(render_text.get())); EXPECT_TRUE(render_text->selection().is_reversed()); @@ -1642,7 +1643,7 @@ TEST_F(RenderTextTest, SelectionKeepsLigatures) { for (size_t i = 0; i < arraysize(kTestStrings); ++i) { render_text->SetText(WideToUTF16(kTestStrings[i])); const int expected_width = render_text->GetStringSize().width(); - render_text->MoveCursorTo(SelectionModel(ui::Range(0, 1), CURSOR_FORWARD)); + render_text->MoveCursorTo(SelectionModel(Range(0, 1), CURSOR_FORWARD)); EXPECT_EQ(expected_width, render_text->GetStringSize().width()); // Draw the text. It shouldn't hit any DCHECKs or crash. // See http://crbug.com/214150 @@ -1651,4 +1652,106 @@ TEST_F(RenderTextTest, SelectionKeepsLigatures) { } } +#if defined(OS_WIN) +// Ensure strings wrap onto multiple lines for a small available width. +TEST_F(RenderTextTest, Multiline_MinWidth) { + const wchar_t* kTestStrings[] = { kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl, + kRtlLtr, kRtlLtrRtl }; + + scoped_ptr<RenderTextWin> render_text( + static_cast<RenderTextWin*>(RenderText::CreateInstance())); + render_text->SetDisplayRect(Rect(1, 1000)); + render_text->SetMultiline(true); + Canvas canvas; + + for (size_t i = 0; i < arraysize(kTestStrings); ++i) { + SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); + render_text->SetText(WideToUTF16(kTestStrings[i])); + render_text->Draw(&canvas); + EXPECT_GT(render_text->lines_.size(), 1U); + } +} + +// Ensure strings wrap onto multiple lines for a normal available width. +TEST_F(RenderTextTest, Multiline_NormalWidth) { + // TODO(ckocagil): Enable this test on XP. +#if defined(OS_WIN) + if (base::win::GetVersion() < base::win::VERSION_VISTA) + return; +#endif + + const struct { + const wchar_t* const text; + const Range first_line_char_range; + const Range second_line_char_range; + } kTestStrings[] = { + { L"abc defg hijkl", Range(0, 9), Range(9, 14) }, + { L"qwertyuiop", Range(0, 8), Range(8, 10) }, + { L"\x062A\x0641\x0627\x062D\x05EA\x05E4\x05D5\x05D6\x05D9\x05DD", + Range(4, 10), Range(0, 4) } + }; + + scoped_ptr<RenderTextWin> render_text( + static_cast<RenderTextWin*>(RenderText::CreateInstance())); + render_text->SetDisplayRect(Rect(50, 1000)); + render_text->SetMultiline(true); + Canvas canvas; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestStrings); ++i) { + SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); + render_text->SetText(WideToUTF16(kTestStrings[i].text)); + render_text->Draw(&canvas); + ASSERT_EQ(2U, render_text->lines_.size()); + ASSERT_EQ(1U, render_text->lines_[0].segments.size()); + EXPECT_EQ(kTestStrings[i].first_line_char_range, + render_text->lines_[0].segments[0].char_range); + ASSERT_EQ(1U, render_text->lines_[1].segments.size()); + EXPECT_EQ(kTestStrings[i].second_line_char_range, + render_text->lines_[1].segments[0].char_range); + } +} + +// Ensure strings don't wrap onto multiple lines for a sufficient available +// width. +TEST_F(RenderTextTest, Multiline_SufficientWidth) { + const wchar_t* kTestStrings[] = { L"", L" ", L".", L" . ", L"abc", L"a b c", + L"\x62E\x628\x632", L"\x62E \x628 \x632" }; + + scoped_ptr<RenderTextWin> render_text( + static_cast<RenderTextWin*>(RenderText::CreateInstance())); + render_text->SetDisplayRect(Rect(30, 1000)); + render_text->SetMultiline(true); + Canvas canvas; + + for (size_t i = 0; i < arraysize(kTestStrings); ++i) { + SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); + render_text->SetText(WideToUTF16(kTestStrings[i])); + render_text->Draw(&canvas); + EXPECT_EQ(1U, render_text->lines_.size()); + } +} +#endif // defined(OS_WIN) + +#if defined(OS_WIN) +TEST_F(RenderTextTest, Win_BreakRunsByUnicodeBlocks) { + scoped_ptr<RenderTextWin> render_text( + static_cast<RenderTextWin*>(RenderText::CreateInstance())); + + render_text->SetText(WideToUTF16(L"x\x25B6y")); + render_text->EnsureLayout(); + ASSERT_EQ(3U, render_text->runs_.size()); + EXPECT_EQ(Range(0, 1), render_text->runs_[0]->range); + EXPECT_EQ(Range(1, 2), render_text->runs_[1]->range); + EXPECT_EQ(Range(2, 3), render_text->runs_[2]->range); + + render_text->SetText(WideToUTF16(L"x \x25B6 y")); + render_text->EnsureLayout(); + ASSERT_EQ(3U, render_text->runs_.size()); + EXPECT_EQ(Range(0, 2), render_text->runs_[0]->range); + EXPECT_EQ(Range(2, 3), render_text->runs_[1]->range); + EXPECT_EQ(Range(3, 5), render_text->runs_[2]->range); + +} +#endif // !defined(OS_WIN) + } // namespace gfx diff --git a/chromium/ui/gfx/render_text_win.cc b/chromium/ui/gfx/render_text_win.cc index ac018de3f44..e283de319ef 100644 --- a/chromium/ui/gfx/render_text_win.cc +++ b/chromium/ui/gfx/render_text_win.cc @@ -7,16 +7,18 @@ #include <algorithm> #include "base/i18n/break_iterator.h" +#include "base/i18n/char_iterator.h" #include "base/i18n/rtl.h" #include "base/logging.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/win/windows_version.h" -#include "ui/base/text/utf16_indexing.h" +#include "third_party/icu/source/common/unicode/uchar.h" #include "ui/gfx/canvas.h" #include "ui/gfx/font_fallback_win.h" #include "ui/gfx/font_smoothing_win.h" #include "ui/gfx/platform_font_win.h" +#include "ui/gfx/utf16_indexing.h" namespace gfx { @@ -132,28 +134,118 @@ bool IsUnicodeBidiControlCharacter(char16 c) { // Returns the corresponding glyph range of the given character range. // |range| is in text-space (0 corresponds to |GetLayoutText()[0]|). // Returned value is in run-space (0 corresponds to the first glyph in the run). -ui::Range CharRangeToGlyphRange(const internal::TextRun& run, - const ui::Range& range) { +Range CharRangeToGlyphRange(const internal::TextRun& run, + const Range& range) { DCHECK(run.range.Contains(range)); DCHECK(!range.is_reversed()); DCHECK(!range.is_empty()); - const ui::Range run_range = ui::Range(range.start() - run.range.start(), - range.end() - run.range.start()); - ui::Range result; + const Range run_range(range.start() - run.range.start(), + range.end() - run.range.start()); + Range result; if (run.script_analysis.fRTL) { - result = ui::Range(run.logical_clusters[run_range.end() - 1], + result = Range(run.logical_clusters[run_range.end() - 1], run_range.start() > 0 ? run.logical_clusters[run_range.start() - 1] : run.glyph_count); } else { - result = ui::Range(run.logical_clusters[run_range.start()], + result = Range(run.logical_clusters[run_range.start()], run_range.end() < run.range.length() ? run.logical_clusters[run_range.end()] : run.glyph_count); } DCHECK(!result.is_reversed()); - DCHECK(ui::Range(0, run.glyph_count).Contains(result)); + DCHECK(Range(0, run.glyph_count).Contains(result)); return result; } +// Starting from |start_char|, finds a suitable line break position at or before +// |available_width| using word break info from |breaks|. If |empty_line| is +// true, this function will not roll back to |start_char| and |*next_char| will +// be greater than |start_char| (to avoid constructing empty lines). +// TODO(ckocagil): Do not break ligatures and diacritics. +// TextRun::logical_clusters might help. +// TODO(ckocagil): We might have to reshape after breaking at ligatures. +// See whether resolving the TODO above resolves this too. +// TODO(ckocagil): Do not reserve width for whitespace at the end of lines. +void BreakRunAtWidth(const internal::TextRun& run, + const BreakList<size_t>& breaks, + size_t start_char, + int available_width, + bool empty_line, + int* width, + size_t* next_char) { + DCHECK(run.range.Contains(Range(start_char, start_char + 1))); + BreakList<size_t>::const_iterator word = breaks.GetBreak(start_char); + BreakList<size_t>::const_iterator next_word = word + 1; + // Width from |std::max(word->first, start_char)| to the current character. + int word_width = 0; + *width = 0; + + for (size_t i = start_char; i < run.range.end(); ++i) { + // |word| holds the word boundary at or before |i|, and |next_word| holds + // the word boundary right after |i|. Advance both |word| and |next_word| + // when |i| reaches |next_word|. + if (next_word != breaks.breaks().end() && i >= next_word->first) { + word = next_word++; + word_width = 0; + } + + Range glyph_range = CharRangeToGlyphRange(run, Range(i, i + 1)); + int char_width = 0; + for (size_t j = glyph_range.start(); j < glyph_range.end(); ++j) + char_width += run.advance_widths[j]; + + *width += char_width; + word_width += char_width; + + if (*width > available_width) { + if (!empty_line || word_width < *width) { + *width -= word_width; + *next_char = std::max(word->first, start_char); + } else if (char_width < *width) { + *width -= char_width; + *next_char = i; + } else { + *next_char = i + 1; + } + + return; + } + } + + *next_char = run.range.end(); +} + +// For segments in the same run, checks the continuity and order of |x_range| +// and |char_range| fields. +void CheckLineIntegrity(const std::vector<internal::Line>& lines, + const ScopedVector<internal::TextRun>& runs) { + size_t previous_segment_line = 0; + const internal::LineSegment* previous_segment = NULL; + + for (size_t i = 0; i < lines.size(); ++i) { + for (size_t j = 0; j < lines[i].segments.size(); ++j) { + const internal::LineSegment* segment = &lines[i].segments[j]; + internal::TextRun* run = runs[segment->run]; + + if (!previous_segment) { + previous_segment = segment; + } else if (runs[previous_segment->run] != run) { + previous_segment = NULL; + } else { + DCHECK_EQ(previous_segment->char_range.end(), + segment->char_range.start()); + if (!run->script_analysis.fRTL) { + DCHECK_EQ(previous_segment->x_range.end(), segment->x_range.start()); + } else { + DCHECK_EQ(segment->x_range.end(), previous_segment->x_range.start()); + } + + previous_segment = segment; + previous_segment_line = i; + } + } + } +} + } // namespace namespace internal { @@ -197,6 +289,183 @@ int GetGlyphXBoundary(const internal::TextRun* run, return run->preceding_run_widths + x; } +// Internal class to generate Line structures. If |multiline| is true, the text +// is broken into lines at |words| boundaries such that each line is no longer +// than |max_width|. If |multiline| is false, only outputs a single Line from +// the given runs. |min_baseline| and |min_height| are the minimum baseline and +// height for each line. +// TODO(ckocagil): Expose the interface of this class in the header and test +// this class directly. +class LineBreaker { + public: + LineBreaker(int max_width, + int min_baseline, + int min_height, + bool multiline, + const BreakList<size_t>* words, + const ScopedVector<TextRun>& runs) + : max_width_(max_width), + min_baseline_(min_baseline), + min_height_(min_height), + multiline_(multiline), + words_(words), + runs_(runs), + text_x_(0), + line_x_(0), + line_ascent_(0), + line_descent_(0) { + AdvanceLine(); + } + + // Breaks the run at given |run_index| into Line structs. + void AddRun(int run_index) { + const TextRun* run = runs_[run_index]; + if (multiline_ && line_x_ + run->width > max_width_) + BreakRun(run_index); + else + AddSegment(run_index, run->range, run->width); + } + + // Finishes line breaking and outputs the results. Can be called at most once. + void Finalize(std::vector<Line>* lines, Size* size) { + DCHECK(!lines_.empty()); + // Add an empty line to finish the line size calculation and remove it. + AdvanceLine(); + lines_.pop_back(); + *size = total_size_; + lines->swap(lines_); + } + + private: + // A (line index, segment index) pair that specifies a segment in |lines_|. + typedef std::pair<size_t, size_t> SegmentHandle; + + LineSegment* SegmentFromHandle(const SegmentHandle& handle) { + return &lines_[handle.first].segments[handle.second]; + } + + // Breaks a run into segments that fit in the last line in |lines_| and adds + // them. Adds a new Line to the back of |lines_| whenever a new segment can't + // be added without the Line's width exceeding |max_width_|. + void BreakRun(int run_index) { + DCHECK(words_); + const TextRun* const run = runs_[run_index]; + int width = 0; + size_t next_char = run->range.start(); + + // Break the run until it fits the current line. + while (next_char < run->range.end()) { + const size_t current_char = next_char; + BreakRunAtWidth(*run, *words_, current_char, max_width_ - line_x_, + line_x_ == 0, &width, &next_char); + AddSegment(run_index, Range(current_char, next_char), width); + if (next_char < run->range.end()) + AdvanceLine(); + } + } + + // RTL runs are broken in logical order but displayed in visual order. To find + // the text-space coordinate (where it would fall in a single-line text) + // |x_range| of RTL segments, segment widths are applied in reverse order. + // e.g. {[5, 10], [10, 40]} will become {[35, 40], [5, 35]}. + void UpdateRTLSegmentRanges() { + if (rtl_segments_.empty()) + return; + int x = SegmentFromHandle(rtl_segments_[0])->x_range.start(); + for (size_t i = rtl_segments_.size(); i > 0; --i) { + LineSegment* segment = SegmentFromHandle(rtl_segments_[i - 1]); + const size_t segment_width = segment->x_range.length(); + segment->x_range = Range(x, x + segment_width); + x += segment_width; + } + rtl_segments_.clear(); + } + + // Finishes the size calculations of the last Line in |lines_|. Adds a new + // Line to the back of |lines_|. + void AdvanceLine() { + if (!lines_.empty()) { + Line* line = &lines_.back(); + // TODO(ckocagil): Determine optimal multiline height behavior. + if (line_ascent_ + line_descent_ == 0) { + line_ascent_ = min_baseline_; + line_descent_ = min_height_ - min_baseline_; + } + // Set the single-line mode Line's metrics to be at least + // |RenderText::font_list()| to not break the current single-line code. + line_ascent_ = std::max(line_ascent_, min_baseline_); + line_descent_ = std::max(line_descent_, min_height_ - min_baseline_); + + line->baseline = line_ascent_; + line->size.set_height(line_ascent_ + line_descent_); + line->preceding_heights = total_size_.height(); + total_size_.set_height(total_size_.height() + line->size.height()); + total_size_.set_width(std::max(total_size_.width(), line->size.width())); + } + line_x_ = 0; + line_ascent_ = 0; + line_descent_ = 0; + lines_.push_back(Line()); + } + + // Adds a new segment with the given properties to |lines_.back()|. + void AddSegment(int run_index, Range char_range, int width) { + if (char_range.is_empty()) { + DCHECK_EQ(width, 0); + return; + } + const TextRun* run = runs_[run_index]; + line_ascent_ = std::max(line_ascent_, run->font.GetBaseline()); + line_descent_ = std::max(line_descent_, + run->font.GetHeight() - run->font.GetBaseline()); + + LineSegment segment; + segment.run = run_index; + segment.char_range = char_range; + segment.x_range = Range(text_x_, text_x_ + width); + + Line* line = &lines_.back(); + line->segments.push_back(segment); + line->size.set_width(line->size.width() + segment.x_range.length()); + if (run->script_analysis.fRTL) { + rtl_segments_.push_back(SegmentHandle(lines_.size() - 1, + line->segments.size() - 1)); + // If this is the last segment of an RTL run, reprocess the text-space x + // ranges of all segments from the run. + if (char_range.end() == run->range.end()) + UpdateRTLSegmentRanges(); + } + text_x_ += width; + line_x_ += width; + } + + const int max_width_; + const int min_baseline_; + const int min_height_; + const bool multiline_; + const BreakList<size_t>* const words_; + const ScopedVector<TextRun>& runs_; + + // Stores the resulting lines. + std::vector<Line> lines_; + + // Text space and line space x coordinates of the next segment to be added. + int text_x_; + int line_x_; + + // Size of the multiline text, not including the currently processed line. + Size total_size_; + + // Ascent and descent values of the current line, |lines_.back()|. + int line_ascent_; + int line_descent_; + + // The current RTL run segments, to be applied by |UpdateRTLSegmentRanges()|. + std::vector<SegmentHandle> rtl_segments_; + + DISALLOW_COPY_AND_ASSIGN(LineBreaker); +}; + } // namespace internal // static @@ -207,7 +476,6 @@ std::map<std::string, Font> RenderTextWin::successful_substitute_fonts_; RenderTextWin::RenderTextWin() : RenderText(), - common_baseline_(0), needs_layout_(false) { set_truncate_length(kMaxUniscribeTextLength); @@ -222,12 +490,12 @@ RenderTextWin::~RenderTextWin() { Size RenderTextWin::GetStringSize() { EnsureLayout(); - return string_size_; + return multiline_string_size_; } int RenderTextWin::GetBaseline() { EnsureLayout(); - return common_baseline_; + return lines()[0].baseline; } SelectionModel RenderTextWin::FindCursorPosition(const Point& point) { @@ -266,8 +534,8 @@ std::vector<RenderText::FontSpan> RenderTextWin::GetFontSpansForTesting() { std::vector<RenderText::FontSpan> spans; for (size_t i = 0; i < runs_.size(); ++i) { spans.push_back(RenderText::FontSpan(runs_[i]->font, - ui::Range(LayoutIndexToTextIndex(runs_[i]->range.start()), - LayoutIndexToTextIndex(runs_[i]->range.end())))); + Range(LayoutIndexToTextIndex(runs_[i]->range.start()), + LayoutIndexToTextIndex(runs_[i]->range.end())))); } return spans; @@ -364,54 +632,61 @@ SelectionModel RenderTextWin::AdjacentWordSelectionModel( return SelectionModel(pos, CURSOR_FORWARD); } -ui::Range RenderTextWin::GetGlyphBounds(size_t index) { +Range RenderTextWin::GetGlyphBounds(size_t index) { const size_t run_index = GetRunContainingCaret(SelectionModel(index, CURSOR_FORWARD)); // Return edge bounds if the index is invalid or beyond the layout text size. if (run_index >= runs_.size()) - return ui::Range(string_size_.width()); + return Range(string_width_); internal::TextRun* run = runs_[run_index]; const size_t layout_index = TextIndexToLayoutIndex(index); - return ui::Range(GetGlyphXBoundary(run, layout_index, false), - GetGlyphXBoundary(run, layout_index, true)); + return Range(GetGlyphXBoundary(run, layout_index, false), + GetGlyphXBoundary(run, layout_index, true)); } -std::vector<Rect> RenderTextWin::GetSubstringBounds(const ui::Range& range) { +std::vector<Rect> RenderTextWin::GetSubstringBounds(const Range& range) { DCHECK(!needs_layout_); - DCHECK(ui::Range(0, text().length()).Contains(range)); - ui::Range layout_range(TextIndexToLayoutIndex(range.start()), - TextIndexToLayoutIndex(range.end())); - DCHECK(ui::Range(0, GetLayoutText().length()).Contains(layout_range)); + DCHECK(Range(0, text().length()).Contains(range)); + Range layout_range(TextIndexToLayoutIndex(range.start()), + TextIndexToLayoutIndex(range.end())); + DCHECK(Range(0, GetLayoutText().length()).Contains(layout_range)); - std::vector<Rect> bounds; + std::vector<Rect> rects; if (layout_range.is_empty()) - return bounds; + return rects; + std::vector<Range> bounds; - // Add a Rect for each run/selection intersection. + // Add a Range for each run/selection intersection. // TODO(msw): The bounds should probably not always be leading the range ends. for (size_t i = 0; i < runs_.size(); ++i) { const internal::TextRun* run = runs_[visual_to_logical_[i]]; - ui::Range intersection = run->range.Intersect(layout_range); + Range intersection = run->range.Intersect(layout_range); if (intersection.IsValid()) { DCHECK(!intersection.is_reversed()); - ui::Range range_x(GetGlyphXBoundary(run, intersection.start(), false), - GetGlyphXBoundary(run, intersection.end(), false)); - Rect rect(range_x.GetMin(), 0, range_x.length(), run->font.GetHeight()); - rect.set_origin(ToViewPoint(rect.origin())); - // Union this with the last rect if they're adjacent. - if (!bounds.empty() && rect.SharesEdgeWith(bounds.back())) { - rect.Union(bounds.back()); + Range range_x(GetGlyphXBoundary(run, intersection.start(), false), + GetGlyphXBoundary(run, intersection.end(), false)); + if (range_x.is_empty()) + continue; + range_x = Range(range_x.GetMin(), range_x.GetMax()); + // Union this with the last range if they're adjacent. + DCHECK(bounds.empty() || bounds.back().GetMax() <= range_x.GetMin()); + if (!bounds.empty() && bounds.back().GetMax() == range_x.GetMin()) { + range_x = Range(bounds.back().GetMin(), range_x.GetMax()); bounds.pop_back(); } - bounds.push_back(rect); + bounds.push_back(range_x); } } - return bounds; + for (size_t i = 0; i < bounds.size(); ++i) { + std::vector<Rect> current_rects = TextBoundsToViewBounds(bounds[i]); + rects.insert(rects.end(), current_rects.begin(), current_rects.end()); + } + return rects; } size_t RenderTextWin::TextIndexToLayoutIndex(size_t index) const { DCHECK_LE(index, text().length()); - ptrdiff_t i = obscured() ? ui::UTF16IndexToOffset(text(), 0, index) : index; + ptrdiff_t i = obscured() ? gfx::UTF16IndexToOffset(text(), 0, index) : index; CHECK_GE(i, 0); // Clamp layout indices to the length of the text actually used for layout. return std::min<size_t>(GetLayoutText().length(), i); @@ -422,7 +697,7 @@ size_t RenderTextWin::LayoutIndexToTextIndex(size_t index) const { return index; DCHECK_LE(index, GetLayoutText().length()); - const size_t text_index = ui::UTF16OffsetToIndex(text(), 0, index); + const size_t text_index = gfx::UTF16OffsetToIndex(text(), 0, index); DCHECK_LE(text_index, text().length()); return text_index; } @@ -437,7 +712,7 @@ bool RenderTextWin::IsCursorablePosition(size_t position) { // and that its glyph has distinct bounds (not mid-multi-character-grapheme). // An example of a multi-character-grapheme that is not a surrogate-pair is: // \x0915\x093f - (ki) - one of many Devanagari biconsonantal conjuncts. - return ui::IsValidCodePointIndex(text(), position) && + return gfx::IsValidCodePointIndex(text(), position) && position < LayoutIndexToTextIndex(GetLayoutText().length()) && GetGlyphBounds(position) != GetGlyphBounds(position - 1); } @@ -448,23 +723,40 @@ void RenderTextWin::ResetLayout() { } void RenderTextWin::EnsureLayout() { - if (!needs_layout_) - return; - // TODO(msw): Skip complex processing if ScriptIsComplex returns false. - ItemizeLogicalText(); - if (!runs_.empty()) - LayoutVisualText(); - needs_layout_ = false; + if (needs_layout_) { + // TODO(msw): Skip complex processing if ScriptIsComplex returns false. + ItemizeLogicalText(); + if (!runs_.empty()) + LayoutVisualText(); + needs_layout_ = false; + std::vector<internal::Line> lines; + set_lines(&lines); + } + + // Compute lines if they're not valid. This is separate from the layout steps + // above to avoid text layout and shaping when we resize |display_rect_|. + if (lines().empty()) { + DCHECK(!needs_layout_); + std::vector<internal::Line> lines; + internal::LineBreaker line_breaker(display_rect().width() - 1, + font_list().GetBaseline(), + font_list().GetHeight(), multiline(), + multiline() ? &GetLineBreaks() : NULL, + runs_); + for (size_t i = 0; i < runs_.size(); ++i) + line_breaker.AddRun(visual_to_logical_[i]); + line_breaker.Finalize(&lines, &multiline_string_size_); + DCHECK(!lines.empty()); +#ifndef NDEBUG + CheckLineIntegrity(lines, runs_); +#endif + set_lines(&lines); + } } void RenderTextWin::DrawVisualText(Canvas* canvas) { DCHECK(!needs_layout_); - - // Skia will draw glyphs with respect to the baseline. - Vector2d offset(GetTextOffset() + Vector2d(0, common_baseline_)); - - SkScalar x = SkIntToScalar(offset.x()); - SkScalar y = SkIntToScalar(offset.y()); + DCHECK(!lines().empty()); std::vector<SkPoint> pos; @@ -481,52 +773,79 @@ void RenderTextWin::DrawVisualText(Canvas* canvas) { ApplyCompositionAndSelectionStyles(); - for (size_t i = 0; i < runs_.size(); ++i) { - // Get the run specified by the visual-to-logical map. - internal::TextRun* run = runs_[visual_to_logical_[i]]; + for (size_t i = 0; i < lines().size(); ++i) { + const internal::Line& line = lines()[i]; + const Vector2d line_offset = GetLineOffset(i); - // Skip painting empty runs and runs outside the display rect area. - if ((run->glyph_count == 0) || (x >= display_rect().right()) || - (x + run->width <= display_rect().x())) { - x += run->width; + // Skip painting empty lines or lines outside the display rect area. + if (!display_rect().Intersects(Rect(PointAtOffsetFromOrigin(line_offset), + line.size))) continue; - } - // Based on WebCore::skiaDrawText. |pos| contains the positions of glyphs. - // An extra terminal |pos| entry is added to simplify width calculations. - pos.resize(run->glyph_count + 1); - SkScalar glyph_x = x; - for (int glyph = 0; glyph < run->glyph_count; glyph++) { - pos[glyph].set(glyph_x + run->offsets[glyph].du, - y + run->offsets[glyph].dv); - glyph_x += SkIntToScalar(run->advance_widths[glyph]); - } - pos.back().set(glyph_x, y); - - renderer.SetTextSize(run->font.GetFontSize()); - renderer.SetFontFamilyWithStyle(run->font.GetFontName(), run->font_style); - - for (BreakList<SkColor>::const_iterator it = - colors().GetBreak(run->range.start()); - it != colors().breaks().end() && it->first < run->range.end(); - ++it) { - const ui::Range glyph_range = CharRangeToGlyphRange(*run, - colors().GetRange(it).Intersect(run->range)); - if (glyph_range.is_empty()) - continue; - renderer.SetForegroundColor(it->second); - renderer.DrawPosText(&pos[glyph_range.start()], - &run->glyphs[glyph_range.start()], - glyph_range.length()); - const SkScalar width = pos[glyph_range.end()].x() - - pos[glyph_range.start()].x(); - renderer.DrawDecorations(pos[glyph_range.start()].x(), y, - SkScalarCeilToInt(width), run->underline, - run->strike, run->diagonal_strike); - } + const Vector2d text_offset = line_offset + Vector2d(0, line.baseline); + int preceding_segment_widths = 0; + + for (size_t j = 0; j < line.segments.size(); ++j) { + const internal::LineSegment* segment = &line.segments[j]; + const int segment_width = segment->x_range.length(); + const internal::TextRun* run = runs_[segment->run]; + DCHECK(!segment->char_range.is_empty()); + DCHECK(run->range.Contains(segment->char_range)); + Range glyph_range = CharRangeToGlyphRange(*run, segment->char_range); + DCHECK(!glyph_range.is_empty()); + // Skip painting segments outside the display rect area. + if (!multiline()) { + const Rect segment_bounds(PointAtOffsetFromOrigin(line_offset) + + Vector2d(preceding_segment_widths, 0), + Size(segment_width, line.size.height())); + if (!display_rect().Intersects(segment_bounds)) { + preceding_segment_widths += segment_width; + continue; + } + } - DCHECK_EQ(glyph_x - x, run->width); - x = glyph_x; + // |pos| contains the positions of glyphs. An extra terminal |pos| entry + // is added to simplify width calculations. + int segment_x = preceding_segment_widths; + pos.resize(glyph_range.length() + 1); + for (size_t k = glyph_range.start(); k < glyph_range.end(); ++k) { + pos[k - glyph_range.start()].set( + SkIntToScalar(text_offset.x() + run->offsets[k].du + segment_x), + SkIntToScalar(text_offset.y() + run->offsets[k].dv)); + segment_x += run->advance_widths[k]; + } + pos.back().set(SkIntToScalar(text_offset.x() + segment_x), + SkIntToScalar(text_offset.y())); + + renderer.SetTextSize(run->font.GetFontSize()); + renderer.SetFontFamilyWithStyle(run->font.GetFontName(), run->font_style); + + for (BreakList<SkColor>::const_iterator it = + colors().GetBreak(segment->char_range.start()); + it != colors().breaks().end() && + it->first < segment->char_range.end(); + ++it) { + const Range intersection = + colors().GetRange(it).Intersect(segment->char_range); + const Range colored_glyphs = CharRangeToGlyphRange(*run, intersection); + DCHECK(glyph_range.Contains(colored_glyphs)); + DCHECK(!colored_glyphs.is_empty()); + const SkPoint& start_pos = + pos[colored_glyphs.start() - glyph_range.start()]; + const SkPoint& end_pos = + pos[colored_glyphs.end() - glyph_range.start()]; + + renderer.SetForegroundColor(it->second); + renderer.DrawPosText(&start_pos, &run->glyphs[colored_glyphs.start()], + colored_glyphs.length()); + renderer.DrawDecorations(start_pos.x(), text_offset.y(), + SkScalarCeilToInt(end_pos.x() - start_pos.x()), + run->underline, run->strike, + run->diagonal_strike); + } + + preceding_segment_widths += segment_width; + } } UndoCompositionAndSelectionStyles(); @@ -534,22 +853,21 @@ void RenderTextWin::DrawVisualText(Canvas* canvas) { void RenderTextWin::ItemizeLogicalText() { runs_.clear(); - // Make |string_size_|'s height and |common_baseline_| tall enough to draw - // often-used characters which are rendered with fonts in the font list. - string_size_ = Size(0, font_list().GetHeight()); - common_baseline_ = font_list().GetBaseline(); + string_width_ = 0; + multiline_string_size_ = Size(); // Set Uniscribe's base text direction. script_state_.uBidiLevel = (GetTextDirection() == base::i18n::RIGHT_TO_LEFT) ? 1 : 0; - if (text().empty()) + const base::string16& layout_text = GetLayoutText(); + if (layout_text.empty()) return; HRESULT hr = E_OUTOFMEMORY; int script_items_count = 0; std::vector<SCRIPT_ITEM> script_items; - const size_t layout_text_length = GetLayoutText().length(); + const size_t layout_text_length = layout_text.length(); // Ensure that |kMaxRuns| is attempted and the loop terminates afterward. for (size_t runs = kGuessRuns; hr == E_OUTOFMEMORY && runs <= kMaxRuns; runs = std::max(runs + 1, std::min(runs * 2, kMaxRuns))) { @@ -557,9 +875,9 @@ void RenderTextWin::ItemizeLogicalText() { // ScriptItemize always adds a terminal array item so that the length of // the last item can be derived from the terminal SCRIPT_ITEM::iCharPos. script_items.resize(runs); - hr = ScriptItemize(GetLayoutText().c_str(), layout_text_length, - runs - 1, &script_control_, &script_state_, - &script_items[0], &script_items_count); + hr = ScriptItemize(layout_text.c_str(), layout_text_length, runs - 1, + &script_control_, &script_state_, &script_items[0], + &script_items_count); } DCHECK(SUCCEEDED(hr)); if (!SUCCEEDED(hr) || script_items_count <= 0) @@ -571,7 +889,7 @@ void RenderTextWin::ItemizeLogicalText() { // Build the list of runs from the script items and ranged styles. Use an // empty color BreakList to avoid breaking runs at color boundaries. BreakList<SkColor> empty_colors; - empty_colors.SetMax(text().length()); + empty_colors.SetMax(layout_text_length); internal::StyleIterator style(empty_colors, styles()); SCRIPT_ITEM* script_item = &script_items[0]; const size_t max_run_length = kMaxGlyphs / 2; @@ -592,9 +910,32 @@ void RenderTextWin::ItemizeLogicalText() { const size_t script_item_break = (script_item + 1)->iCharPos; run_break = std::min(script_item_break, TextIndexToLayoutIndex(style.GetRange().end())); + // Clamp run lengths to avoid exceeding the maximum supported glyph count. - if ((run_break - run->range.start()) > max_run_length) + if ((run_break - run->range.start()) > max_run_length) { run_break = run->range.start() + max_run_length; + if (!gfx::IsValidCodePointIndex(layout_text, run_break)) + --run_break; + } + + // Break runs between characters in different code blocks. This avoids using + // fallback fonts for more characters than needed. http://crbug.com/278913 + if (run_break > run->range.start()) { + const size_t run_start = run->range.start(); + const int32 run_length = static_cast<int32>(run_break - run_start); + base::i18n::UTF16CharIterator iter(layout_text.c_str() + run_start, + run_length); + const UBlockCode first_block_code = ublock_getCode(iter.get()); + while (iter.Advance() && iter.array_pos() < run_length) { + if (ublock_getCode(iter.get()) != first_block_code) { + run_break = run_start + iter.array_pos(); + break; + } + } + } + + DCHECK(gfx::IsValidCodePointIndex(layout_text, run_break)); + style.UpdatePosition(LayoutIndexToTextIndex(run_break)); if (script_item_break == run_break) script_item++; @@ -643,8 +984,6 @@ void RenderTextWin::LayoutVisualText() { DCHECK(SUCCEEDED(hr)); } } - string_size_.set_height(ascent + descent); - common_baseline_ = ascent; // Build the array of bidirectional embedding levels. scoped_ptr<BYTE[]> levels(new BYTE[runs_.size()]); @@ -669,7 +1008,7 @@ void RenderTextWin::LayoutVisualText() { run->width = abc.abcA + abc.abcB + abc.abcC; preceding_run_widths += run->width; } - string_size_.set_width(preceding_run_widths); + string_width_ = preceding_run_widths; } void RenderTextWin::LayoutTextRun(internal::TextRun* run) { @@ -684,7 +1023,6 @@ void RenderTextWin::LayoutTextRun(internal::TextRun* run) { // in the case where no font is able to display the entire run. int best_partial_font_missing_char_count = INT_MAX; Font best_partial_font = original_font; - bool using_best_partial_font = false; Font current_font; run->logical_clusters.reset(new WORD[run_length]); diff --git a/chromium/ui/gfx/render_text_win.h b/chromium/ui/gfx/render_text_win.h index 620ef092dff..423e31fcad5 100644 --- a/chromium/ui/gfx/render_text_win.h +++ b/chromium/ui/gfx/render_text_win.h @@ -23,7 +23,7 @@ struct TextRun { TextRun(); ~TextRun(); - ui::Range range; + Range range; Font font; // A gfx::Font::FontStyle flag to specify bold and italic styles. // Supersedes |font.GetFontStyle()|. Stored separately to avoid calling @@ -76,8 +76,8 @@ class RenderTextWin : public RenderText { virtual SelectionModel AdjacentWordSelectionModel( const SelectionModel& selection, VisualCursorDirection direction) OVERRIDE; - virtual ui::Range GetGlyphBounds(size_t index) OVERRIDE; - virtual std::vector<Rect> GetSubstringBounds(const ui::Range& range) OVERRIDE; + virtual Range GetGlyphBounds(size_t index) OVERRIDE; + virtual std::vector<Rect> GetSubstringBounds(const Range& range) OVERRIDE; virtual size_t TextIndexToLayoutIndex(size_t index) const OVERRIDE; virtual size_t LayoutIndexToTextIndex(size_t index) const OVERRIDE; virtual bool IsCursorablePosition(size_t position) OVERRIDE; @@ -86,7 +86,10 @@ class RenderTextWin : public RenderText { virtual void DrawVisualText(Canvas* canvas) OVERRIDE; private: + FRIEND_TEST_ALL_PREFIXES(RenderTextTest, Win_BreakRunsByUnicodeBlocks); FRIEND_TEST_ALL_PREFIXES(RenderTextTest, Win_LogicalClusters); + FRIEND_TEST_ALL_PREFIXES(RenderTextTest, Multiline_MinWidth); + FRIEND_TEST_ALL_PREFIXES(RenderTextTest, Multiline_NormalWidth); void ItemizeLogicalText(); void LayoutVisualText(); @@ -121,11 +124,12 @@ class RenderTextWin : public RenderText { SCRIPT_STATE script_state_; ScopedVector<internal::TextRun> runs_; - Size string_size_; - // A common vertical baseline for all the text runs. This is computed as the - // largest baseline over all the runs' fonts. - int common_baseline_; + // Single line width of the layout text. + int string_width_; + + // Wrapped multiline size of the layout text. + Size multiline_string_size_; scoped_ptr<int[]> visual_to_logical_; scoped_ptr<int[]> logical_to_visual_; diff --git a/chromium/ui/gfx/safe_integer_conversions.h b/chromium/ui/gfx/safe_integer_conversions.h index edd8a4cafee..523b1f3441f 100644 --- a/chromium/ui/gfx/safe_integer_conversions.h +++ b/chromium/ui/gfx/safe_integer_conversions.h @@ -8,7 +8,7 @@ #include <cmath> #include <limits> -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" namespace gfx { diff --git a/chromium/ui/base/gtk/scoped_gobject.h b/chromium/ui/gfx/scoped_gobject.h index 2e62e8f2c83..860849ec84e 100644 --- a/chromium/ui/base/gtk/scoped_gobject.h +++ b/chromium/ui/gfx/scoped_gobject.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_GTK_SCOPED_GOBJECT_H_ -#define UI_BASE_GTK_SCOPED_GOBJECT_H_ +#ifndef UI_GFX_SCOPED_GOBJECT_H_ +#define UI_GFX_SCOPED_GOBJECT_H_ #include <glib-object.h> @@ -31,4 +31,4 @@ struct ScopedGObject { } // namespace ui -#endif // UI_BASE_GTK_SCOPED_GOBJECT_H_ +#endif // UI_GFX_SCOPED_GOBJECT_H_ diff --git a/chromium/ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h b/chromium/ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h index f4b11ad228e..9b0b77829b6 100644 --- a/chromium/ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h +++ b/chromium/ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h @@ -6,7 +6,7 @@ #define UI_GFX_SCOPED_NS_GRAPHICS_CONTEXT_SAVE_GSTATE_MAC_H_ #include "base/basictypes.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #if defined(__OBJC__) @class NSGraphicsContext; diff --git a/chromium/ui/gfx/screen.h b/chromium/ui/gfx/screen.h index 9410d028889..a181cc8d256 100644 --- a/chromium/ui/gfx/screen.h +++ b/chromium/ui/gfx/screen.h @@ -5,9 +5,11 @@ #ifndef UI_GFX_SCREEN_H_ #define UI_GFX_SCREEN_H_ +#include <vector> + #include "base/basictypes.h" -#include "ui/base/ui_export.h" #include "ui/gfx/display.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/point.h" #include "ui/gfx/screen_type_delegate.h" @@ -18,6 +20,11 @@ class Rect; // A utility class for getting various info about screen size, displays, // cursor position, etc. +// +// Note that this class does not represent an individual display connected to a +// computer -- see the Display class for that. A single Screen object exists on +// most operating systems regardless of the number of connected displays. On +// Windows 8, two Screens exist: one for Metro UI and another for the desktop. class UI_EXPORT Screen { public: // Retrieves the Screen that the specified NativeView belongs to. A value of @@ -50,17 +57,23 @@ class UI_EXPORT Screen { virtual gfx::Point GetCursorScreenPoint() = 0; // Returns the window under the cursor. - virtual gfx::NativeWindow GetWindowAtCursorScreenPoint() = 0; + virtual gfx::NativeWindow GetWindowUnderCursor() = 0; + + // Returns the window at the given screen coordinate |point|. + virtual gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) = 0; // Returns the number of displays. // Mirrored displays are excluded; this method is intended to return the // number of distinct, usable displays. - virtual int GetNumDisplays() = 0; + virtual int GetNumDisplays() const = 0; + + // Returns the list of displays that are currently available. + virtual std::vector<gfx::Display> GetAllDisplays() const = 0; // Returns the display nearest the specified window. virtual gfx::Display GetDisplayNearestWindow(NativeView view) const = 0; - // Returns the the display nearest the specified point. + // Returns the display nearest the specified point. virtual gfx::Display GetDisplayNearestPoint( const gfx::Point& point) const = 0; diff --git a/chromium/ui/gfx/screen_android.cc b/chromium/ui/gfx/screen_android.cc index 6c4d63325d6..e90bb76725d 100644 --- a/chromium/ui/gfx/screen_android.cc +++ b/chromium/ui/gfx/screen_android.cc @@ -19,7 +19,13 @@ class ScreenAndroid : public Screen { virtual gfx::Point GetCursorScreenPoint() OVERRIDE { return gfx::Point(); } - virtual gfx::NativeWindow GetWindowAtCursorScreenPoint() OVERRIDE { + virtual gfx::NativeWindow GetWindowUnderCursor() OVERRIDE { + NOTIMPLEMENTED(); + return NULL; + } + + virtual gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) + OVERRIDE { NOTIMPLEMENTED(); return NULL; } @@ -50,7 +56,11 @@ class ScreenAndroid : public Screen { return GetPrimaryDisplay(); } - virtual int GetNumDisplays() OVERRIDE { return 1; } + virtual int GetNumDisplays() const OVERRIDE { return 1; } + + virtual std::vector<gfx::Display> GetAllDisplays() const OVERRIDE { + return std::vector<gfx::Display>(1, GetPrimaryDisplay()); + } virtual gfx::Display GetDisplayMatching( const gfx::Rect& match_rect) const OVERRIDE { diff --git a/chromium/ui/gfx/screen_gtk.cc b/chromium/ui/gfx/screen_gtk.cc index 8ef803dca1f..ac2464bbbd7 100644 --- a/chromium/ui/gfx/screen_gtk.cc +++ b/chromium/ui/gfx/screen_gtk.cc @@ -47,14 +47,20 @@ bool GetScreenWorkArea(gfx::Rect* out_rect) { return true; } -gfx::Rect NativePrimaryMonitorBounds() { - GdkScreen* screen = gdk_screen_get_default(); - GdkRectangle rect; - gdk_screen_get_monitor_geometry(screen, 0, &rect); - return gfx::Rect(rect); +gfx::Display GetDisplayForMonitorNum(GdkScreen* screen, gint monitor_num) { + GdkRectangle bounds; + gdk_screen_get_monitor_geometry(screen, monitor_num, &bounds); + // Use |monitor_num| as display id. + gfx::Display display(monitor_num, gfx::Rect(bounds)); + if (gdk_screen_get_primary_monitor(screen) == monitor_num) { + gfx::Rect rect; + if (GetScreenWorkArea(&rect)) + display.set_work_area(gfx::IntersectRects(rect, display.bounds())); + } + return display; } -gfx::Rect GetMonitorAreaNearestWindow(gfx::NativeView view) { +gfx::Display GetMonitorAreaNearestWindow(gfx::NativeView view) { GdkScreen* screen = gdk_screen_get_default(); gint monitor_num = 0; if (view && GTK_IS_WINDOW(view)) { @@ -66,9 +72,7 @@ gfx::Rect GetMonitorAreaNearestWindow(gfx::NativeView view) { screen, gtk_widget_get_window(top_level)); } - GdkRectangle bounds; - gdk_screen_get_monitor_geometry(screen, monitor_num, &bounds); - return gfx::Rect(bounds); + return GetDisplayForMonitorNum(screen, monitor_num); } class ScreenGtk : public gfx::Screen { @@ -90,7 +94,7 @@ class ScreenGtk : public gfx::Screen { } // Returns the window under the cursor. - virtual gfx::NativeWindow GetWindowAtCursorScreenPoint() OVERRIDE { + virtual gfx::NativeWindow GetWindowUnderCursor() OVERRIDE { GdkWindow* window = gdk_window_at_pointer(NULL, NULL); if (!window) return NULL; @@ -104,20 +108,34 @@ class ScreenGtk : public gfx::Screen { return GTK_IS_WINDOW(widget) ? GTK_WINDOW(widget) : NULL; } + virtual gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) + OVERRIDE { + NOTIMPLEMENTED(); + return NULL; + } + // Returns the number of displays. // Mirrored displays are excluded; this method is intended to return the // number of distinct, usable displays. - virtual int GetNumDisplays() OVERRIDE { + virtual int GetNumDisplays() const OVERRIDE { // This query is kinda bogus for Linux -- do we want number of X screens? // The number of monitors Xinerama has? We'll just use whatever GDK uses. GdkScreen* screen = gdk_screen_get_default(); return gdk_screen_get_n_monitors(screen); } + virtual std::vector<gfx::Display> GetAllDisplays() const OVERRIDE { + GdkScreen* screen = gdk_screen_get_default(); + gint num_of_displays = gdk_screen_get_n_monitors(screen); + std::vector<gfx::Display> all_displays; + for (gint i = 0; i < num_of_displays; ++i) + all_displays.push_back(GetDisplayForMonitorNum(screen, i)); + return all_displays; + } + // Returns the display nearest the specified window. virtual gfx::Display GetDisplayNearestWindow( gfx::NativeView view) const OVERRIDE { - gfx::Rect bounds = GetMonitorAreaNearestWindow(view); // Do not use the _NET_WORKAREA here, this is supposed to be an area on a // specific monitor, and _NET_WORKAREA is a hint from the WM that // generally spans across all monitors. This would make the work area @@ -127,8 +145,8 @@ class ScreenGtk : public gfx::Screen { // means to compute this rect would be to watch all windows with // _NET_WM_STRUT(_PARTIAL) hints, and subtract their space from the // physical area of the display to construct a work area. - // TODO(oshima): Implement ID and Observer. - return gfx::Display(0, bounds); + // TODO(oshima): Implement Observer. + return GetMonitorAreaNearestWindow(view); } // Returns the the display nearest the specified point. @@ -137,32 +155,36 @@ class ScreenGtk : public gfx::Screen { GdkScreen* screen = gdk_screen_get_default(); gint monitor = gdk_screen_get_monitor_at_point( screen, point.x(), point.y()); - GdkRectangle bounds; - gdk_screen_get_monitor_geometry(screen, monitor, &bounds); - // TODO(oshima): Implement ID and Observer. - return gfx::Display(0, gfx::Rect(bounds)); + // TODO(oshima): Implement Observer. + return GetDisplayForMonitorNum(screen, monitor); } // Returns the display that most closely intersects the provided bounds. virtual gfx::Display GetDisplayMatching( const gfx::Rect& match_rect) const OVERRIDE { - // TODO(thestig) Implement multi-monitor support. - return GetPrimaryDisplay(); + std::vector<gfx::Display> displays = GetAllDisplays(); + gfx::Display maxIntersectDisplay; + gfx::Rect maxIntersection; + for (std::vector<gfx::Display>::iterator it = displays.begin(); + it != displays.end(); ++it) { + gfx::Rect displayIntersection = it->bounds(); + displayIntersection.Intersect(match_rect); + if (displayIntersection.size().GetArea() > + maxIntersection.size().GetArea()) { + maxIntersectDisplay = *it; + maxIntersection = displayIntersection; + } + } + return maxIntersectDisplay.is_valid() ? + maxIntersectDisplay : GetPrimaryDisplay(); } // Returns the primary display. virtual gfx::Display GetPrimaryDisplay() const OVERRIDE { - gfx::Rect bounds = NativePrimaryMonitorBounds(); - // TODO(oshima): Implement ID and Observer. - gfx::Display display(0, bounds); - gfx::Rect rect; - if (GetScreenWorkArea(&rect)) { - display.set_work_area(gfx::IntersectRects(rect, bounds)); - } else { - // Return the best we've got. - display.set_work_area(bounds); - } - return display; + GdkScreen* screen = gdk_screen_get_default(); + gint primary_monitor_index = gdk_screen_get_primary_monitor(screen); + // TODO(oshima): Implement Observer. + return GetDisplayForMonitorNum(screen, primary_monitor_index); } virtual void AddObserver(gfx::DisplayObserver* observer) OVERRIDE { diff --git a/chromium/ui/gfx/screen_ios.mm b/chromium/ui/gfx/screen_ios.mm index dfb0d1b62bb..a2770298ca8 100644 --- a/chromium/ui/gfx/screen_ios.mm +++ b/chromium/ui/gfx/screen_ios.mm @@ -21,12 +21,18 @@ class ScreenIos : public gfx::Screen { return gfx::Point(0, 0); } - virtual gfx::NativeWindow GetWindowAtCursorScreenPoint() OVERRIDE { + virtual gfx::NativeWindow GetWindowUnderCursor() OVERRIDE { NOTIMPLEMENTED(); return gfx::NativeWindow(); } - virtual int GetNumDisplays() OVERRIDE { + virtual gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) + OVERRIDE { + NOTIMPLEMENTED(); + return gfx::NativeWindow(); + } + + virtual int GetNumDisplays() const OVERRIDE { #if TARGET_IPHONE_SIMULATOR // UIScreen does not reliably return correct results on the simulator. return 1; @@ -35,6 +41,11 @@ class ScreenIos : public gfx::Screen { #endif } + virtual std::vector<gfx::Display> GetAllDisplays() const OVERRIDE { + NOTIMPLEMENTED(); + return std::vector<gfx::Display>(1, GetPrimaryDisplay()); + } + // Returns the display nearest the specified window. virtual gfx::Display GetDisplayNearestWindow( gfx::NativeView view) const OVERRIDE { diff --git a/chromium/ui/gfx/screen_mac.mm b/chromium/ui/gfx/screen_mac.mm index d9e1f0a71c9..28707ca7ea3 100644 --- a/chromium/ui/gfx/screen_mac.mm +++ b/chromium/ui/gfx/screen_mac.mm @@ -84,12 +84,18 @@ class ScreenMac : public gfx::Screen { return gfx::Point(mouseLocation.x, mouseLocation.y); } - virtual gfx::NativeWindow GetWindowAtCursorScreenPoint() OVERRIDE { + virtual gfx::NativeWindow GetWindowUnderCursor() OVERRIDE { NOTIMPLEMENTED(); return gfx::NativeWindow(); } - virtual int GetNumDisplays() OVERRIDE { + virtual gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) + OVERRIDE { + NOTIMPLEMENTED(); + return gfx::NativeWindow(); + } + + virtual int GetNumDisplays() const OVERRIDE { // Don't just return the number of online displays. It includes displays // that mirror other displays, which are not desired in the count. It's // tempting to use the count returned by CGGetActiveDisplayList, but active @@ -123,6 +129,11 @@ class ScreenMac : public gfx::Screen { return display_count; } + virtual std::vector<gfx::Display> GetAllDisplays() const OVERRIDE { + NOTIMPLEMENTED(); + return std::vector<gfx::Display>(1, GetPrimaryDisplay()); + } + virtual gfx::Display GetDisplayNearestWindow( gfx::NativeView view) const OVERRIDE { NSWindow* window = [view window]; diff --git a/chromium/ui/gfx/screen_win.cc b/chromium/ui/gfx/screen_win.cc index 06c14bd1732..7903cc5fdd5 100644 --- a/chromium/ui/gfx/screen_win.cc +++ b/chromium/ui/gfx/screen_win.cc @@ -6,28 +6,47 @@ #include <windows.h> +#include "base/hash.h" #include "base/logging.h" -#include "ui/base/win/dpi.h" +#include "base/strings/utf_string_conversions.h" +#include "base/win/win_util.h" #include "ui/gfx/display.h" +#include "ui/gfx/win/dpi.h" namespace { -MONITORINFO GetMonitorInfoForMonitor(HMONITOR monitor) { - MONITORINFO monitor_info = { 0 }; +MONITORINFOEX GetMonitorInfoForMonitor(HMONITOR monitor) { + MONITORINFOEX monitor_info; + ZeroMemory(&monitor_info, sizeof(MONITORINFOEX)); monitor_info.cbSize = sizeof(monitor_info); - GetMonitorInfo(monitor, &monitor_info); + base::win::GetMonitorInfoWrapper(monitor, &monitor_info); return monitor_info; } -gfx::Display GetDisplay(MONITORINFO& monitor_info) { - // TODO(oshima): Implement ID and Observer. +gfx::Display GetDisplay(MONITORINFOEX& monitor_info) { + // TODO(oshima): Implement Observer. + int64 id = static_cast<int64>(base::Hash(WideToUTF8(monitor_info.szDevice))); gfx::Rect bounds = gfx::Rect(monitor_info.rcMonitor); - gfx::Display display(0, bounds); + gfx::Display display(id, bounds); display.set_work_area(gfx::Rect(monitor_info.rcWork)); - display.SetScaleAndBounds(ui::win::GetDeviceScaleFactor(), bounds); + display.SetScaleAndBounds(gfx::win::GetDeviceScaleFactor(), bounds); return display; } +BOOL CALLBACK EnumMonitorCallback(HMONITOR monitor, + HDC hdc, + LPRECT rect, + LPARAM data) { + std::vector<gfx::Display>* all_displays = + reinterpret_cast<std::vector<gfx::Display>*>(data); + DCHECK(all_displays); + + MONITORINFOEX monitor_info = GetMonitorInfoForMonitor(monitor); + gfx::Display display = GetDisplay(monitor_info); + all_displays->push_back(display); + return TRUE; +} + } // namespace namespace gfx { @@ -39,7 +58,7 @@ ScreenWin::~ScreenWin() { } bool ScreenWin::IsDIPEnabled() { - return ui::IsInHighDPIMode(); + return IsInHighDPIMode(); } gfx::Point ScreenWin::GetCursorScreenPoint() { @@ -48,16 +67,27 @@ gfx::Point ScreenWin::GetCursorScreenPoint() { return gfx::Point(pt); } -gfx::NativeWindow ScreenWin::GetWindowAtCursorScreenPoint() { - POINT location; - HWND window_hwnd = GetCursorPos(&location) ? WindowFromPoint(location) : NULL; - return GetNativeWindowFromHWND(window_hwnd); +gfx::NativeWindow ScreenWin::GetWindowUnderCursor() { + POINT cursor_loc; + HWND hwnd = GetCursorPos(&cursor_loc) ? WindowFromPoint(cursor_loc) : NULL; + return GetNativeWindowFromHWND(hwnd); +} + +gfx::NativeWindow ScreenWin::GetWindowAtScreenPoint(const gfx::Point& point) { + return GetNativeWindowFromHWND(WindowFromPoint(point.ToPOINT())); } -int ScreenWin::GetNumDisplays() { +int ScreenWin::GetNumDisplays() const { return GetSystemMetrics(SM_CMONITORS); } +std::vector<gfx::Display> ScreenWin::GetAllDisplays() const { + std::vector<gfx::Display> all_displays; + EnumDisplayMonitors(NULL, NULL, EnumMonitorCallback, + reinterpret_cast<LPARAM>(&all_displays)); + return all_displays; +} + gfx::Display ScreenWin::GetDisplayNearestWindow(gfx::NativeView window) const { HWND window_hwnd = GetHWNDFromNativeView(window); if (!window_hwnd) { @@ -67,37 +97,39 @@ gfx::Display ScreenWin::GetDisplayNearestWindow(gfx::NativeView window) const { return GetPrimaryDisplay(); } - MONITORINFO monitor_info; + MONITORINFOEX monitor_info; monitor_info.cbSize = sizeof(monitor_info); - GetMonitorInfo(MonitorFromWindow(window_hwnd, MONITOR_DEFAULTTONEAREST), - &monitor_info); + base::win::GetMonitorInfoWrapper( + MonitorFromWindow(window_hwnd, MONITOR_DEFAULTTONEAREST), &monitor_info); return GetDisplay(monitor_info); } gfx::Display ScreenWin::GetDisplayNearestPoint(const gfx::Point& point) const { POINT initial_loc = { point.x(), point.y() }; HMONITOR monitor = MonitorFromPoint(initial_loc, MONITOR_DEFAULTTONEAREST); - MONITORINFO mi = {0}; + MONITORINFOEX mi; + ZeroMemory(&mi, sizeof(MONITORINFOEX)); mi.cbSize = sizeof(mi); - if (monitor && GetMonitorInfo(monitor, &mi)) + if (monitor && base::win::GetMonitorInfoWrapper(monitor, &mi)) { return GetDisplay(mi); + } return gfx::Display(); } gfx::Display ScreenWin::GetDisplayMatching(const gfx::Rect& match_rect) const { RECT other_bounds_rect = match_rect.ToRECT(); - MONITORINFO monitor_info = GetMonitorInfoForMonitor(MonitorFromRect( + MONITORINFOEX monitor_info = GetMonitorInfoForMonitor(MonitorFromRect( &other_bounds_rect, MONITOR_DEFAULTTONEAREST)); return GetDisplay(monitor_info); } gfx::Display ScreenWin::GetPrimaryDisplay() const { - MONITORINFO mi = GetMonitorInfoForMonitor( + MONITORINFOEX mi = GetMonitorInfoForMonitor( MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY)); gfx::Display display = GetDisplay(mi); // TODO(kevers|girard): Test if these checks can be reintroduced for high-DIP // once more of the app is DIP-aware. - if (!ui::IsInHighDPIMode()) { + if (!IsInHighDPIMode()) { DCHECK_EQ(GetSystemMetrics(SM_CXSCREEN), display.size().width()); DCHECK_EQ(GetSystemMetrics(SM_CYSCREEN), display.size().height()); } diff --git a/chromium/ui/gfx/screen_win.h b/chromium/ui/gfx/screen_win.h index f6b7d40ae8d..a9fb7f518ff 100644 --- a/chromium/ui/gfx/screen_win.h +++ b/chromium/ui/gfx/screen_win.h @@ -6,7 +6,7 @@ #define UI_GFX_SCREEN_WIN_H_ #include "base/compiler_specific.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/screen.h" namespace gfx { @@ -20,8 +20,11 @@ class UI_EXPORT ScreenWin : public gfx::Screen { // Overridden from gfx::Screen: virtual bool IsDIPEnabled() OVERRIDE; virtual gfx::Point GetCursorScreenPoint() OVERRIDE; - virtual gfx::NativeWindow GetWindowAtCursorScreenPoint() OVERRIDE; - virtual int GetNumDisplays() OVERRIDE; + virtual gfx::NativeWindow GetWindowUnderCursor() OVERRIDE; + virtual gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) + OVERRIDE; + virtual int GetNumDisplays() const OVERRIDE; + virtual std::vector<gfx::Display> GetAllDisplays() const OVERRIDE; virtual gfx::Display GetDisplayNearestWindow( gfx::NativeView window) const OVERRIDE; virtual gfx::Display GetDisplayNearestPoint( diff --git a/chromium/ui/gfx/scrollbar_size.h b/chromium/ui/gfx/scrollbar_size.h index 43f1ca5ee5e..d11774d17a7 100644 --- a/chromium/ui/gfx/scrollbar_size.h +++ b/chromium/ui/gfx/scrollbar_size.h @@ -5,7 +5,7 @@ #ifndef UI_GFX_SCROLLBAR_SIZE_H_ #define UI_GFX_SCROLLBAR_SIZE_H_ -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" namespace gfx { diff --git a/chromium/ui/gfx/selection_model.cc b/chromium/ui/gfx/selection_model.cc index c3a31dae107..5352d8653cd 100644 --- a/chromium/ui/gfx/selection_model.cc +++ b/chromium/ui/gfx/selection_model.cc @@ -10,14 +10,17 @@ namespace gfx { SelectionModel::SelectionModel() - : selection_(0), caret_affinity_(CURSOR_BACKWARD) {} + : selection_(0), + caret_affinity_(CURSOR_BACKWARD) {} SelectionModel::SelectionModel(size_t position, LogicalCursorDirection affinity) - : selection_(position), caret_affinity_(affinity) {} + : selection_(position), + caret_affinity_(affinity) {} -SelectionModel::SelectionModel(ui::Range selection, +SelectionModel::SelectionModel(const Range& selection, LogicalCursorDirection affinity) - : selection_(selection), caret_affinity_(affinity) {} + : selection_(selection), + caret_affinity_(affinity) {} bool SelectionModel::operator==(const SelectionModel& sel) const { return selection_ == sel.selection() && diff --git a/chromium/ui/gfx/selection_model.h b/chromium/ui/gfx/selection_model.h index b99b383714b..0b811d1c5ce 100644 --- a/chromium/ui/gfx/selection_model.h +++ b/chromium/ui/gfx/selection_model.h @@ -7,8 +7,8 @@ #include <string> -#include "ui/base/range/range.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" +#include "ui/gfx/range/range.h" namespace gfx { @@ -67,9 +67,9 @@ class UI_EXPORT SelectionModel { SelectionModel(size_t position, LogicalCursorDirection affinity); // Create a SelectionModel representing a selection (which may be empty). // The caret position is the end of the range. - SelectionModel(ui::Range selection, LogicalCursorDirection affinity); + SelectionModel(const Range& selection, LogicalCursorDirection affinity); - const ui::Range& selection() const { return selection_; } + const Range& selection() const { return selection_; } size_t caret_pos() const { return selection_.end(); } LogicalCursorDirection caret_affinity() const { return caret_affinity_; } @@ -87,7 +87,7 @@ class UI_EXPORT SelectionModel { void set_selection_start(size_t pos) { selection_.set_start(pos); } // Logical selection. The logical caret position is the end of the selection. - ui::Range selection_; + Range selection_; // The logical direction from the caret position (selection_.end()) to the // character it is attached to for display purposes. This matters only when diff --git a/chromium/ui/gfx/shadow_value.h b/chromium/ui/gfx/shadow_value.h index d07ac94043b..46d84b4be3f 100644 --- a/chromium/ui/gfx/shadow_value.h +++ b/chromium/ui/gfx/shadow_value.h @@ -9,7 +9,7 @@ #include <vector> #include "third_party/skia/include/core/SkColor.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/point.h" namespace gfx { diff --git a/chromium/ui/gfx/size.h b/chromium/ui/gfx/size.h index f6152a3aa12..c2340ebce63 100644 --- a/chromium/ui/gfx/size.h +++ b/chromium/ui/gfx/size.h @@ -8,7 +8,7 @@ #include <string> #include "base/compiler_specific.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/size_base.h" #include "ui/gfx/size_f.h" diff --git a/chromium/ui/gfx/size_base.h b/chromium/ui/gfx/size_base.h index 6f23fa3cedb..72d47d2c37b 100644 --- a/chromium/ui/gfx/size_base.h +++ b/chromium/ui/gfx/size_base.h @@ -5,7 +5,7 @@ #ifndef UI_GFX_SIZE_BASE_H_ #define UI_GFX_SIZE_BASE_H_ -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" namespace gfx { diff --git a/chromium/ui/gfx/size_f.h b/chromium/ui/gfx/size_f.h index a38d3f6caff..ee90189f7d9 100644 --- a/chromium/ui/gfx/size_f.h +++ b/chromium/ui/gfx/size_f.h @@ -8,7 +8,7 @@ #include <string> #include "base/compiler_specific.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/size_base.h" namespace gfx { diff --git a/chromium/ui/gfx/skbitmap_operations.h b/chromium/ui/gfx/skbitmap_operations.h index eb41d0f7090..3a0d3c97504 100644 --- a/chromium/ui/gfx/skbitmap_operations.h +++ b/chromium/ui/gfx/skbitmap_operations.h @@ -6,8 +6,8 @@ #define UI_GFX_SKBITMAP_OPERATIONS_H_ #include "base/gtest_prod_util.h" -#include "ui/base/ui_export.h" #include "ui/gfx/color_utils.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/shadow_value.h" namespace gfx { diff --git a/chromium/ui/gfx/skia_util.h b/chromium/ui/gfx/skia_util.h index 4a2cfcf2035..592ff5f2f66 100644 --- a/chromium/ui/gfx/skia_util.h +++ b/chromium/ui/gfx/skia_util.h @@ -12,7 +12,7 @@ #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkShader.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" class SkBitmap; class SkDrawLooper; diff --git a/chromium/ui/gfx/skia_utils_gtk.h b/chromium/ui/gfx/skia_utils_gtk.h index 6d56e0fab8a..abe397722ac 100644 --- a/chromium/ui/gfx/skia_utils_gtk.h +++ b/chromium/ui/gfx/skia_utils_gtk.h @@ -6,7 +6,7 @@ #define UI_GFX_SKIA_UTILS_GTK_H_ #include "third_party/skia/include/core/SkColor.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" typedef struct _GdkColor GdkColor; diff --git a/chromium/ui/gfx/switches.cc b/chromium/ui/gfx/switches.cc index 55452c3c7c7..2f2eb9a3b82 100644 --- a/chromium/ui/gfx/switches.cc +++ b/chromium/ui/gfx/switches.cc @@ -4,7 +4,6 @@ #include "ui/gfx/switches.h" -namespace gfx { namespace switches { // Let text glyphs have X-positions that aren't snapped to the pixel grid in @@ -17,5 +16,10 @@ const char kEnableBrowserTextSubpixelPositioning[] = const char kEnableWebkitTextSubpixelPositioning[] = "enable-webkit-text-subpixel-positioning"; +// Overrides the device scale factor for the browser UI and the contents. +const char kForceDeviceScaleFactor[] = "force-device-scale-factor"; + +// Enables/Disables High DPI support (windows) +const char kHighDPISupport[] = "high-dpi-support"; + } // namespace switches -} // namespace gfx diff --git a/chromium/ui/gfx/switches.h b/chromium/ui/gfx/switches.h index 3bae4521f7d..e3cd9e7db85 100644 --- a/chromium/ui/gfx/switches.h +++ b/chromium/ui/gfx/switches.h @@ -5,15 +5,15 @@ #ifndef UI_GFX_SWITCHES_H_ #define UI_GFX_SWITCHES_H_ -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" -namespace gfx { namespace switches { UI_EXPORT extern const char kEnableBrowserTextSubpixelPositioning[]; UI_EXPORT extern const char kEnableWebkitTextSubpixelPositioning[]; +UI_EXPORT extern const char kForceDeviceScaleFactor[]; +UI_EXPORT extern const char kHighDPISupport[]; } // namespace switches -} // namespace gfx #endif // UI_GFX_SWITCHES_H_ diff --git a/chromium/ui/gfx/sys_color_change_listener.cc b/chromium/ui/gfx/sys_color_change_listener.cc index 7a9fc84478f..d5646b3a81c 100644 --- a/chromium/ui/gfx/sys_color_change_listener.cc +++ b/chromium/ui/gfx/sys_color_change_listener.cc @@ -13,7 +13,7 @@ #include "base/memory/singleton.h" #include "base/observer_list.h" #if defined(OS_WIN) -#include "ui/base/win/singleton_hwnd.h" +#include "ui/gfx/win/singleton_hwnd.h" #endif namespace gfx { @@ -48,7 +48,7 @@ bool IsInvertedColorScheme() { } #if defined(OS_WIN) -class SysColorChangeObserver : public ui::SingletonHwnd::Observer { +class SysColorChangeObserver : public gfx::SingletonHwnd::Observer { public: static SysColorChangeObserver* GetInstance(); @@ -75,11 +75,11 @@ SysColorChangeObserver* SysColorChangeObserver::GetInstance() { } SysColorChangeObserver::SysColorChangeObserver() { - ui::SingletonHwnd::GetInstance()->AddObserver(this); + gfx::SingletonHwnd::GetInstance()->AddObserver(this); } SysColorChangeObserver::~SysColorChangeObserver() { - ui::SingletonHwnd::GetInstance()->RemoveObserver(this); + gfx::SingletonHwnd::GetInstance()->RemoveObserver(this); } void SysColorChangeObserver::AddListener(SysColorChangeListener* listener) { diff --git a/chromium/ui/gfx/sys_color_change_listener.h b/chromium/ui/gfx/sys_color_change_listener.h index 2d196630b5e..db3f9df74cc 100644 --- a/chromium/ui/gfx/sys_color_change_listener.h +++ b/chromium/ui/gfx/sys_color_change_listener.h @@ -7,7 +7,7 @@ #include "base/basictypes.h" #include "third_party/skia/include/core/SkColor.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" namespace gfx { diff --git a/chromium/ui/base/text/text_elider.cc b/chromium/ui/gfx/text_elider.cc index 05909816cf3..bc4eb3bb858 100644 --- a/chromium/ui/base/text/text_elider.cc +++ b/chromium/ui/gfx/text_elider.cc @@ -7,7 +7,7 @@ // Note that several of the functions declared in text_elider.h are implemented // in this file using helper classes in an unnamed namespace. -#include "ui/base/text/text_elider.h" +#include "ui/gfx/text_elider.h" #include <string> #include <vector> @@ -26,10 +26,11 @@ #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "third_party/icu/source/common/unicode/rbbi.h" #include "third_party/icu/source/common/unicode/uloc.h" -#include "ui/gfx/font.h" +#include "ui/gfx/font_list.h" +#include "ui/gfx/text_utils.h" #include "url/gurl.h" -namespace ui { +namespace gfx { // U+2026 in utf8 const char kEllipsis[] = "\xE2\x80\xA6"; @@ -115,7 +116,7 @@ string16 BuildPathFromComponents(const string16& path_prefix, // Add |filename|, ellipsis if necessary. if (num_components != (path_elements.size() - 1)) - path += UTF8ToUTF16(kEllipsis) + kForwardSlash; + path += string16(kEllipsisUTF16) + kForwardSlash; path += filename; return path; @@ -128,7 +129,7 @@ string16 ElideComponentizedPath(const string16& url_path_prefix, const std::vector<string16>& url_path_elements, const string16& url_filename, const string16& url_query, - const gfx::Font& font, + const gfx::FontList& font_list, int available_pixel_width) { const size_t url_path_number_of_elements = url_path_elements.size(); @@ -136,9 +137,9 @@ string16 ElideComponentizedPath(const string16& url_path_prefix, for (size_t i = url_path_number_of_elements - 1; i > 0; --i) { string16 elided_path = BuildPathFromComponents(url_path_prefix, url_path_elements, url_filename, i); - if (available_pixel_width >= font.GetStringWidth(elided_path)) - return ElideText(elided_path + url_query, - font, available_pixel_width, ELIDE_AT_END); + if (available_pixel_width >= gfx::GetStringWidth(elided_path, font_list)) + return ElideText(elided_path + url_query, font_list, + available_pixel_width, ELIDE_AT_END); } return string16(); @@ -147,9 +148,9 @@ string16 ElideComponentizedPath(const string16& url_path_prefix, } // namespace string16 ElideEmail(const string16& email, - const gfx::Font& font, + const gfx::FontList& font_list, int available_pixel_width) { - if (font.GetStringWidth(email) <= available_pixel_width) + if (gfx::GetStringWidth(email, font_list) <= available_pixel_width) return email; // Split the email into its local-part (username) and domain-part. The email @@ -166,16 +167,17 @@ string16 ElideEmail(const string16& email, // Subtract the @ symbol from the available width as it is mandatory. const string16 kAtSignUTF16 = ASCIIToUTF16("@"); - available_pixel_width -= font.GetStringWidth(kAtSignUTF16); + available_pixel_width -= gfx::GetStringWidth(kAtSignUTF16, font_list); // Check whether eliding the domain is necessary: if eliding the username // is sufficient, the domain will not be elided. - const int full_username_width = font.GetStringWidth(username); + const int full_username_width = gfx::GetStringWidth(username, font_list); const int available_domain_width = available_pixel_width - std::min(full_username_width, - font.GetStringWidth(username.substr(0, 1) + kEllipsisUTF16)); - if (font.GetStringWidth(domain) > available_domain_width) { + gfx::GetStringWidth(username.substr(0, 1) + kEllipsisUTF16, + font_list)); + if (gfx::GetStringWidth(domain, font_list) > available_domain_width) { // Elide the domain so that it only takes half of the available width. // Should the username not need all the width available in its half, the // domain will occupy the leftover width. @@ -186,7 +188,8 @@ string16 ElideEmail(const string16& email, std::min(available_domain_width, std::max(available_pixel_width - full_username_width, available_pixel_width / 2)); - domain = ElideText(domain, font, desired_domain_width, ELIDE_IN_MIDDLE); + domain = ElideText(domain, font_list, desired_domain_width, + ELIDE_IN_MIDDLE); // Failing to elide the domain such that at least one character remains // (other than the ellipsis itself) remains: return a single ellipsis. if (domain.length() <= 1U) @@ -196,20 +199,25 @@ string16 ElideEmail(const string16& email, // Fit the username in the remaining width (at this point the elided username // is guaranteed to fit with at least one character remaining given all the // precautions taken earlier). - username = ElideText(username, - font, - available_pixel_width - font.GetStringWidth(domain), + available_pixel_width -= gfx::GetStringWidth(domain, font_list); + username = ElideText(username, font_list, available_pixel_width, ELIDE_AT_END); return username + kAtSignUTF16 + domain; } +string16 ElideEmail(const string16& email, + const gfx::Font& font, + int available_pixel_width) { + return ElideEmail(email, gfx::FontList(font), available_pixel_width); +} + // TODO(pkasting): http://crbug.com/77883 This whole function gets // kerning/ligatures/etc. issues potentially wrong by assuming that the width of // a rendered string is always the sum of the widths of its substrings. Also I // suspect it could be made simpler. string16 ElideUrl(const GURL& url, - const gfx::Font& font, + const gfx::FontList& font_list, int available_pixel_width, const std::string& languages) { // Get a formatted string and corresponding parsing of the url. @@ -222,11 +230,12 @@ string16 ElideUrl(const GURL& url, // If non-standard, return plain eliding. if (!url.IsStandard()) - return ElideText(url_string, font, available_pixel_width, ELIDE_AT_END); + return ElideText(url_string, font_list, available_pixel_width, + ELIDE_AT_END); // Now start eliding url_string to fit within available pixel width. // Fist pass - check to see whether entire url_string fits. - const int pixel_width_url_string = font.GetStringWidth(url_string); + const int pixel_width_url_string = gfx::GetStringWidth(url_string, font_list); if (available_pixel_width >= pixel_width_url_string) return url_string; @@ -239,8 +248,9 @@ string16 ElideUrl(const GURL& url, // Return general elided text if url minus the query fits. const string16 url_minus_query = url_string.substr(0, path_start_index + path_len); - if (available_pixel_width >= font.GetStringWidth(url_minus_query)) - return ElideText(url_string, font, available_pixel_width, ELIDE_AT_END); + if (available_pixel_width >= gfx::GetStringWidth(url_minus_query, font_list)) + return ElideText(url_string, font_list, available_pixel_width, + ELIDE_AT_END); // Get Host. string16 url_host = UTF8ToUTF16(url.host()); @@ -288,15 +298,17 @@ string16 ElideUrl(const GURL& url, } // Second Pass - remove scheme - the rest fits. - const int pixel_width_url_host = font.GetStringWidth(url_host); - const int pixel_width_url_path = font.GetStringWidth(url_path_query_etc); + const int pixel_width_url_host = gfx::GetStringWidth(url_host, font_list); + const int pixel_width_url_path = gfx::GetStringWidth(url_path_query_etc, + font_list); if (available_pixel_width >= pixel_width_url_host + pixel_width_url_path) return url_host + url_path_query_etc; // Third Pass: Subdomain, domain and entire path fits. - const int pixel_width_url_domain = font.GetStringWidth(url_domain); - const int pixel_width_url_subdomain = font.GetStringWidth(url_subdomain); + const int pixel_width_url_domain = gfx::GetStringWidth(url_domain, font_list); + const int pixel_width_url_subdomain = gfx::GetStringWidth(url_subdomain, + font_list); if (available_pixel_width >= pixel_width_url_subdomain + pixel_width_url_domain + pixel_width_url_path) @@ -304,15 +316,15 @@ string16 ElideUrl(const GURL& url, // Query element. string16 url_query; - const int kPixelWidthDotsTrailer = - font.GetStringWidth(UTF8ToUTF16(kEllipsis)); + const int kPixelWidthDotsTrailer = gfx::GetStringWidth( + string16(kEllipsisUTF16), font_list); if (parsed.query.is_nonempty()) { url_query = UTF8ToUTF16("?") + url_string.substr(parsed.query.begin); - if (available_pixel_width >= (pixel_width_url_subdomain + - pixel_width_url_domain + pixel_width_url_path - - font.GetStringWidth(url_query))) { + if (available_pixel_width >= + (pixel_width_url_subdomain + pixel_width_url_domain + + pixel_width_url_path - gfx::GetStringWidth(url_query, font_list))) { return ElideText(url_subdomain + url_domain + url_path_query_etc, - font, available_pixel_width, ELIDE_AT_END); + font_list, available_pixel_width, ELIDE_AT_END); } } @@ -339,18 +351,19 @@ string16 ElideUrl(const GURL& url, url_path_number_of_elements > kMaxNumberOfUrlPathElementsAllowed) { // No path to elide, or too long of a path (could overflow in loop below) // Just elide this as a text string. - return ElideText(url_subdomain + url_domain + url_path_query_etc, font, + return ElideText(url_subdomain + url_domain + url_path_query_etc, font_list, available_pixel_width, ELIDE_AT_END); } // Start eliding the path and replacing elements by ".../". - const string16 kEllipsisAndSlash = UTF8ToUTF16(kEllipsis) + kForwardSlash; - const int pixel_width_ellipsis_slash = font.GetStringWidth(kEllipsisAndSlash); + const string16 kEllipsisAndSlash = string16(kEllipsisUTF16) + kForwardSlash; + const int pixel_width_ellipsis_slash = gfx::GetStringWidth(kEllipsisAndSlash, + font_list); // Check with both subdomain and domain. string16 elided_path = ElideComponentizedPath(url_subdomain + url_domain, url_path_elements, - url_filename, url_query, font, + url_filename, url_query, font_list, available_pixel_width); if (!elided_path.empty()) return elided_path; @@ -368,7 +381,7 @@ string16 ElideUrl(const GURL& url, url_elided_domain = url_domain; elided_path = ElideComponentizedPath(url_elided_domain, url_path_elements, - url_filename, url_query, font, + url_filename, url_query, font_list, available_pixel_width); if (!elided_path.empty()) @@ -377,24 +390,32 @@ string16 ElideUrl(const GURL& url, // Return elided domain/.../filename anyway. string16 final_elided_url_string(url_elided_domain); - const int url_elided_domain_width = font.GetStringWidth(url_elided_domain); + const int url_elided_domain_width = gfx::GetStringWidth(url_elided_domain, + font_list); // A hack to prevent trailing ".../...". if ((available_pixel_width - url_elided_domain_width) > pixel_width_ellipsis_slash + kPixelWidthDotsTrailer + - font.GetStringWidth(ASCIIToUTF16("UV"))) { + gfx::GetStringWidth(ASCIIToUTF16("UV"), font_list)) { final_elided_url_string += BuildPathFromComponents(string16(), url_path_elements, url_filename, 1); } else { final_elided_url_string += url_path; } - return ElideText(final_elided_url_string, font, available_pixel_width, + return ElideText(final_elided_url_string, font_list, available_pixel_width, ELIDE_AT_END); } +string16 ElideUrl(const GURL& url, + const gfx::Font& font, + int available_pixel_width, + const std::string& languages) { + return ElideUrl(url, gfx::FontList(font), available_pixel_width, languages); +} + string16 ElideFilename(const base::FilePath& filename, - const gfx::Font& font, + const gfx::FontList& font_list, int available_pixel_width) { #if defined(OS_WIN) string16 filename_utf16 = filename.value(); @@ -409,18 +430,18 @@ string16 ElideFilename(const base::FilePath& filename, filename.BaseName().RemoveExtension().value())); #endif - const int full_width = font.GetStringWidth(filename_utf16); + const int full_width = gfx::GetStringWidth(filename_utf16, font_list); if (full_width <= available_pixel_width) return base::i18n::GetDisplayStringInLTRDirectionality(filename_utf16); if (rootname.empty() || extension.empty()) { - const string16 elided_name = ElideText(filename_utf16, font, + const string16 elided_name = ElideText(filename_utf16, font_list, available_pixel_width, ELIDE_AT_END); return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); } - const int ext_width = font.GetStringWidth(extension); - const int root_width = font.GetStringWidth(rootname); + const int ext_width = gfx::GetStringWidth(extension, font_list); + const int root_width = gfx::GetStringWidth(rootname, font_list); // We may have trimmed the path. if (root_width + ext_width <= available_pixel_width) { @@ -429,7 +450,7 @@ string16 ElideFilename(const base::FilePath& filename, } if (ext_width >= available_pixel_width) { - const string16 elided_name = ElideText(rootname + extension, font, + const string16 elided_name = ElideText(rootname + extension, font_list, available_pixel_width, ELIDE_IN_MIDDLE); return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); @@ -437,19 +458,25 @@ string16 ElideFilename(const base::FilePath& filename, int available_root_width = available_pixel_width - ext_width; string16 elided_name = - ElideText(rootname, font, available_root_width, ELIDE_AT_END); + ElideText(rootname, font_list, available_root_width, ELIDE_AT_END); elided_name += extension; return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); } +string16 ElideFilename(const base::FilePath& filename, + const gfx::Font& font, + int available_pixel_width) { + return ElideFilename(filename, gfx::FontList(font), available_pixel_width); +} + string16 ElideText(const string16& text, - const gfx::Font& font, + const gfx::FontList& font_list, int available_pixel_width, ElideBehavior elide_behavior) { if (text.empty()) return text; - const int current_text_pixel_width = font.GetStringWidth(text); + const int current_text_pixel_width = gfx::GetStringWidth(text, font_list); const bool elide_in_middle = (elide_behavior == ELIDE_IN_MIDDLE); const bool insert_ellipsis = (elide_behavior != TRUNCATE_AT_END); @@ -466,13 +493,14 @@ string16 ElideText(const string16& text, // ridiculous), but we should check other widths for bogus values as well. if (current_text_pixel_width <= 0 && !text.empty()) { const string16 cut = slicer.CutString(text.length() / 2, false); - return ElideText(cut, font, available_pixel_width, elide_behavior); + return ElideText(cut, font_list, available_pixel_width, elide_behavior); } if (current_text_pixel_width <= available_pixel_width) return text; - if (insert_ellipsis && font.GetStringWidth(ellipsis) > available_pixel_width) + if (insert_ellipsis && + gfx::GetStringWidth(ellipsis, font_list) > available_pixel_width) return string16(); // Use binary search to compute the elided text. @@ -483,12 +511,12 @@ string16 ElideText(const string16& text, // We check the length of the whole desired string at once to ensure we // handle kerning/ligatures/etc. correctly. const string16 cut = slicer.CutString(guess, insert_ellipsis); - const int guess_length = font.GetStringWidth(cut); + const int guess_length = gfx::GetStringWidth(cut, font_list); // Check again that we didn't hit a Pango width overflow. If so, cut the // current string in half and start over. if (guess_length <= 0) { return ElideText(slicer.CutString(guess / 2, false), - font, available_pixel_width, elide_behavior); + font_list, available_pixel_width, elide_behavior); } if (guess_length > available_pixel_width) hi = guess - 1; @@ -499,6 +527,14 @@ string16 ElideText(const string16& text, return slicer.CutString(guess, insert_ellipsis); } +string16 ElideText(const string16& text, + const gfx::Font& font, + int available_pixel_width, + ElideBehavior elide_behavior) { + return ElideText(text, gfx::FontList(font), available_pixel_width, + elide_behavior); +} + SortedDisplayURL::SortedDisplayURL(const GURL& url, const std::string& languages) { net::AppendFormattedHost(url, languages, &sort_host_); @@ -606,8 +642,6 @@ bool ElideString(const string16& input, int max_len, string16* output) { return true; } -} // namespace ui - namespace { // Internal class used to track progress of a rectangular string elide @@ -775,13 +809,13 @@ void RectangleString::NewLine(bool output) { // can be broken into smaller methods sharing this state. class RectangleText { public: - RectangleText(const gfx::Font& font, + RectangleText(const gfx::FontList& font_list, int available_pixel_width, int available_pixel_height, - ui::WordWrapBehavior wrap_behavior, + WordWrapBehavior wrap_behavior, std::vector<string16>* lines) - : font_(font), - line_height_(font.GetHeight()), + : font_list_(font_list), + line_height_(font_list.GetHeight()), available_pixel_width_(available_pixel_width), available_pixel_height_(available_pixel_height), wrap_behavior_(wrap_behavior), @@ -833,8 +867,8 @@ class RectangleText { // Set the current position to the beginning of the next line. bool NewLine(); - // The font used for measuring text width. - const gfx::Font& font_; + // The font list used for measuring text width. + const gfx::FontList& font_list_; // The height of each line of text. const int line_height_; @@ -846,7 +880,7 @@ class RectangleText { const int available_pixel_height_; // The wrap behavior for words that are too long to fit on a single line. - const ui::WordWrapBehavior wrap_behavior_; + const WordWrapBehavior wrap_behavior_; // The current running width. int current_width_; @@ -902,12 +936,12 @@ int RectangleText::Finalize() { } if (last_line_ended_in_lf_) lines_->push_back(string16()); - return (insufficient_width_ ? ui::INSUFFICIENT_SPACE_HORIZONTAL : 0) | - (insufficient_height_ ? ui::INSUFFICIENT_SPACE_VERTICAL : 0); + return (insufficient_width_ ? INSUFFICIENT_SPACE_HORIZONTAL : 0) | + (insufficient_height_ ? INSUFFICIENT_SPACE_VERTICAL : 0); } void RectangleText::AddLine(const string16& line) { - const int line_width = font_.GetStringWidth(line); + const int line_width = gfx::GetStringWidth(line, font_list_); if (line_width <= available_pixel_width_) { AddToCurrentLineWithWidth(line, line_width); } else { @@ -948,7 +982,8 @@ int RectangleText::WrapWord(const string16& word) { bool first_fragment = true; while (!insufficient_height_ && !text.empty()) { string16 fragment = - ui::ElideText(text, font_, available_pixel_width_, ui::TRUNCATE_AT_END); + ElideText(text, font_list_, available_pixel_width_, + TRUNCATE_AT_END); // At least one character has to be added at every line, even if the // available space is too small. if(fragment.empty()) @@ -972,17 +1007,16 @@ int RectangleText::AddWordOverflow(const string16& word) { lines_added++; } - if (wrap_behavior_ == ui::IGNORE_LONG_WORDS) { + if (wrap_behavior_ == IGNORE_LONG_WORDS) { current_line_ = word; current_width_ = available_pixel_width_; - } else if (wrap_behavior_ == ui::WRAP_LONG_WORDS) { + } else if (wrap_behavior_ == WRAP_LONG_WORDS) { lines_added += WrapWord(word); } else { - const ui::ElideBehavior elide_behavior = - (wrap_behavior_ == ui::ELIDE_LONG_WORDS ? ui::ELIDE_AT_END : - ui::TRUNCATE_AT_END); + const ElideBehavior elide_behavior = + (wrap_behavior_ == ELIDE_LONG_WORDS ? ELIDE_AT_END : TRUNCATE_AT_END); const string16 elided_word = - ui::ElideText(word, font_, available_pixel_width_, elide_behavior); + ElideText(word, font_list_, available_pixel_width_, elide_behavior); AddToCurrentLine(elided_word); insufficient_width_ = true; } @@ -994,7 +1028,7 @@ int RectangleText::AddWord(const string16& word) { int lines_added = 0; string16 trimmed; TrimWhitespace(word, TRIM_TRAILING, &trimmed); - const int trimmed_width = font_.GetStringWidth(trimmed); + const int trimmed_width = gfx::GetStringWidth(trimmed, font_list_); if (trimmed_width <= available_pixel_width_) { // Word can be made to fit, no need to fragment it. if ((current_width_ + trimmed_width > available_pixel_width_) && NewLine()) @@ -1002,14 +1036,14 @@ int RectangleText::AddWord(const string16& word) { // Append the non-trimmed word, in case more words are added after. AddToCurrentLine(word); } else { - lines_added = AddWordOverflow(wrap_behavior_ == ui::IGNORE_LONG_WORDS ? + lines_added = AddWordOverflow(wrap_behavior_ == IGNORE_LONG_WORDS ? trimmed : word); } return lines_added; } void RectangleText::AddToCurrentLine(const string16& text) { - AddToCurrentLineWithWidth(text, font_.GetStringWidth(text)); + AddToCurrentLineWithWidth(text, gfx::GetStringWidth(text, font_list_)); } void RectangleText::AddToCurrentLineWithWidth(const string16& text, @@ -1038,8 +1072,6 @@ bool RectangleText::NewLine() { } // namespace -namespace ui { - bool ElideRectangleString(const string16& input, size_t max_rows, size_t max_cols, bool strict, string16* output) { RectangleString rect(max_rows, max_cols, strict, output); @@ -1049,12 +1081,12 @@ bool ElideRectangleString(const string16& input, size_t max_rows, } int ElideRectangleText(const string16& input, - const gfx::Font& font, - int available_pixel_width, - int available_pixel_height, - WordWrapBehavior wrap_behavior, - std::vector<string16>* lines) { - RectangleText rect(font, + const gfx::FontList& font_list, + int available_pixel_width, + int available_pixel_height, + WordWrapBehavior wrap_behavior, + std::vector<string16>* lines) { + RectangleText rect(font_list, available_pixel_width, available_pixel_height, wrap_behavior, @@ -1064,6 +1096,17 @@ int ElideRectangleText(const string16& input, return rect.Finalize(); } +int ElideRectangleText(const string16& input, + const gfx::Font& font, + int available_pixel_width, + int available_pixel_height, + WordWrapBehavior wrap_behavior, + std::vector<string16>* lines) { + return ElideRectangleText(input, gfx::FontList(font), + available_pixel_width, available_pixel_height, + wrap_behavior, lines); +} + string16 TruncateString(const string16& string, size_t length) { if (string.size() <= length) // String fits, return it. @@ -1126,4 +1169,4 @@ string16 TruncateString(const string16& string, size_t length) { return string.substr(0, index) + kElideString; } -} // namespace ui +} // namespace gfx diff --git a/chromium/ui/base/text/text_elider.h b/chromium/ui/gfx/text_elider.h index 1d31f8eea63..008a1cd1b5b 100644 --- a/chromium/ui/base/text/text_elider.h +++ b/chromium/ui/gfx/text_elider.h @@ -4,8 +4,8 @@ // // This file defines utility functions for eliding and formatting UI text. -#ifndef UI_BASE_TEXT_TEXT_ELIDER_H_ -#define UI_BASE_TEXT_TEXT_ELIDER_H_ +#ifndef UI_GFX_TEXT_ELIDER_H_ +#define UI_GFX_TEXT_ELIDER_H_ #include <string> #include <vector> @@ -14,8 +14,7 @@ #include "base/strings/string16.h" #include "third_party/icu/source/common/unicode/uchar.h" #include "third_party/icu/source/i18n/unicode/coll.h" -#include "ui/base/ui_export.h" -#include "ui/gfx/font.h" +#include "ui/gfx/gfx_export.h" class GURL; @@ -23,13 +22,15 @@ namespace base { class FilePath; } -namespace ui { +namespace gfx { +class Font; +class FontList; UI_EXPORT extern const char kEllipsis[]; UI_EXPORT extern const char16 kEllipsisUTF16[]; // Elides a well-formed email address (e.g. username@domain.com) to fit into -// |available_pixel_width| using the specified |font|. +// |available_pixel_width| using the specified |font_list|. // This function guarantees that the string returned will contain at least one // character, other than the ellipses, on either side of the '@'. If it is // impossible to achieve these requirements: only an ellipsis will be returned. @@ -39,6 +40,10 @@ UI_EXPORT extern const char16 kEllipsisUTF16[]; // doesn't need half the available width: the elided domain will occupy that // extra width). UI_EXPORT string16 ElideEmail(const string16& email, + const gfx::FontList& font_list, + int available_pixel_width); +// Obsolete version. Use the above version which takes gfx::FontList. +UI_EXPORT string16 ElideEmail(const string16& email, const gfx::Font& font, int available_pixel_width); @@ -57,6 +62,11 @@ UI_EXPORT string16 ElideEmail(const string16& email, // is displayed properly in an RTL context. Please refer to // http://crbug.com/6487 for more information. UI_EXPORT string16 ElideUrl(const GURL& url, + const gfx::FontList& font_list, + int available_pixel_width, + const std::string& languages); +// Obsolete version. Use the above version which takes gfx::FontList. +UI_EXPORT string16 ElideUrl(const GURL& url, const gfx::Font& font, int available_pixel_width, const std::string& languages); @@ -73,6 +83,11 @@ enum ElideBehavior { // Elides |text| to fit in |available_pixel_width| according to the specified // |elide_behavior|. UI_EXPORT string16 ElideText(const string16& text, + const gfx::FontList& font_list, + int available_pixel_width, + ElideBehavior elide_behavior); +// Obsolete version. Use the above version which takes gfx::FontList. +UI_EXPORT string16 ElideText(const string16& text, const gfx::Font& font, int available_pixel_width, ElideBehavior elide_behavior); @@ -84,6 +99,10 @@ UI_EXPORT string16 ElideText(const string16& text, // the elided filename is wrapped with LRE (Left-To-Right Embedding) mark and // PDF (Pop Directional Formatting) mark. UI_EXPORT string16 ElideFilename(const base::FilePath& filename, + const gfx::FontList& font_list, + int available_pixel_width); +// Obsolete version. Use the above version which takes gfx::FontList. +UI_EXPORT string16 ElideFilename(const base::FilePath& filename, const gfx::Font& font, int available_pixel_width); @@ -181,12 +200,19 @@ enum ReformattingResultFlags { // Reformats |text| into output vector |lines| so that the resulting text fits // into an |available_pixel_width| by |available_pixel_height| rectangle with -// the specified |font|. Input newlines are respected, but lines that are too -// long are broken into pieces. For words that are too wide to fit on a single -// line, the wrapping behavior can be specified with the |wrap_behavior| param. -// Returns a combination of |ReformattingResultFlags| that indicate whether the -// given rectangle had insufficient space to accommodate |texŧ|, leading to -// elision or truncation (and not just reformatting). +// the specified |font_list|. Input newlines are respected, but lines that are +// too long are broken into pieces. For words that are too wide to fit on a +// single line, the wrapping behavior can be specified with the |wrap_behavior| +// param. Returns a combination of |ReformattingResultFlags| that indicate +// whether the given rectangle had insufficient space to accommodate |texŧ|, +// leading to elision or truncation (and not just reformatting). +UI_EXPORT int ElideRectangleText(const string16& text, + const gfx::FontList& font_list, + int available_pixel_width, + int available_pixel_height, + WordWrapBehavior wrap_behavior, + std::vector<string16>* lines); +// Obsolete version. Use the above version which takes gfx::FontList. UI_EXPORT int ElideRectangleText(const string16& text, const gfx::Font& font, int available_pixel_width, @@ -201,6 +227,6 @@ UI_EXPORT int ElideRectangleText(const string16& text, // less. UI_EXPORT string16 TruncateString(const string16& string, size_t length); -} // namespace ui +} // namespace gfx -#endif // UI_BASE_TEXT_TEXT_ELIDER_H_ +#endif // UI_GFX_TEXT_ELIDER_H_ diff --git a/chromium/ui/base/text/text_elider_unittest.cc b/chromium/ui/gfx/text_elider_unittest.cc index 3c06cb543cf..2a90e5d73cb 100644 --- a/chromium/ui/base/text/text_elider_unittest.cc +++ b/chromium/ui/gfx/text_elider_unittest.cc @@ -4,7 +4,7 @@ // // Unit tests for eliding and formatting utility functions. -#include "ui/base/text/text_elider.h" +#include "ui/gfx/text_elider.h" #include "base/files/file_path.h" #include "base/i18n/rtl.h" @@ -15,7 +15,7 @@ #include "ui/gfx/font.h" #include "url/gurl.h" -namespace ui { +namespace gfx { namespace { @@ -53,6 +53,20 @@ void RunUrlTest(Testcase* testcases, size_t num_testcases) { } } +gfx::Font GetTestingFont() { + gfx::Font font; +#if defined(OS_MACOSX) + // Use a specific font for certain tests on Mac. + // 1) Different Mac machines might be configured with different default font. + // The number of extra pixels needed to make ElideEmail/TestFilenameEliding + // tests work might vary per the default font. + // 2) This specific font helps expose the line width exceeding problem as in + // ElideRectangleTextCheckLineWidth. + font = gfx::Font("LucidaGrande", 12); +#endif + return font; +} + } // namespace // TODO(ios): Complex eliding is off by one for some of those tests on iOS. @@ -107,13 +121,22 @@ TEST(TextEliderTest, MAYBE_ElideEmail) { {"mmmmm@llllllllll", "m" + kEllipsisStr + "@l" + kEllipsisStr}, }; - const gfx::Font font; + const gfx::Font font = GetTestingFont(); for (size_t i = 0; i < arraysize(testcases); ++i) { const string16 expected_output = UTF8ToUTF16(testcases[i].output); + int available_width = font.GetStringWidth(expected_output); +#if defined(OS_MACOSX) + // Give two extra pixels to offset the ceiling width returned by + // GetStringWidth on Mac. This workaround will no longer be needed once + // the floating point width is adopted (http://crbug.com/288987). + // Note that we need one more pixel than TestFilenameEliding because + // multiple strings are elided and we need to offset more. + available_width += 2; +#endif EXPECT_EQ(expected_output, ElideEmail(UTF8ToUTF16(testcases[i].input), font, - font.GetStringWidth(expected_output))); + available_width)); } } @@ -311,14 +334,19 @@ TEST(TextEliderTest, MAYBE_TestFilenameEliding) { "file.name.re" + kEllipsisStr + "emelylongext"} }; - static const gfx::Font font; + static const gfx::Font font = GetTestingFont(); for (size_t i = 0; i < arraysize(testcases); ++i) { base::FilePath filepath(testcases[i].input); string16 expected = UTF8ToUTF16(testcases[i].output); expected = base::i18n::GetDisplayStringInLTRDirectionality(expected); - EXPECT_EQ(expected, ElideFilename(filepath, - font, - font.GetStringWidth(UTF8ToUTF16(testcases[i].output)))); + int available_width = font.GetStringWidth(UTF8ToUTF16(testcases[i].output)); +#if defined(OS_MACOSX) + // Give one extra pixel to offset the ceiling width returned by + // GetStringWidth on Mac. This workaround will no longer be needed once + // the floating point width is adopted (http://crbug.com/288987). + available_width += 1; +#endif + EXPECT_EQ(expected, ElideFilename(filepath, font, available_width)); } } @@ -707,6 +735,37 @@ TEST(TextEliderTest, ElideRectangleTextLongWords) { } } +// TODO(ios): Complex eliding is off by one for some of those tests on iOS. +// See crbug.com/154019 +#if defined(OS_IOS) +#define MAYBE_ElideRectangleTextCheckLineWidth \ + DISABLED_ElideRectangleTextCheckLineWidth +#else +#define MAYBE_ElideRectangleTextCheckLineWidth ElideRectangleTextCheckLineWidth +#endif + +// This test is to make sure that the width of each wrapped line does not +// exceed the available width. On some platform like Mac, this test used to +// fail because the truncated integer width is returned for the string +// and the accumulation of the truncated values causes the elide function +// to wrap incorrectly. +TEST(TextEliderTest, MAYBE_ElideRectangleTextCheckLineWidth) { + gfx::Font font = GetTestingFont(); + const int kAvailableWidth = 235; + const int kAvailableHeight = 1000; + const char text[] = "that Russian place we used to go to after fencing"; + std::vector<string16> lines; + EXPECT_EQ(0, ElideRectangleText(UTF8ToUTF16(text), + font, + kAvailableWidth, + kAvailableHeight, + WRAP_LONG_WORDS, + &lines)); + ASSERT_EQ(2u, lines.size()); + EXPECT_LE(font.GetStringWidth(lines[0]), kAvailableWidth); + EXPECT_LE(font.GetStringWidth(lines[1]), kAvailableWidth); +} + TEST(TextEliderTest, ElideRectangleString) { struct TestData { const char* input; @@ -931,4 +990,4 @@ TEST(TextEliderTest, TruncateString) { EXPECT_EQ(L"\x2026", UTF16ToWide(TruncateString(ASCIIToUTF16(" "), 2))); } -} // namespace ui +} // namespace gfx diff --git a/chromium/ui/gfx/text_utils.h b/chromium/ui/gfx/text_utils.h index 42bce439731..bd94902fba6 100644 --- a/chromium/ui/gfx/text_utils.h +++ b/chromium/ui/gfx/text_utils.h @@ -6,10 +6,12 @@ #define UI_GFX_TEXT_UTILS_H_ #include "base/strings/string16.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" namespace gfx { +class FontList; + // Strip the accelerator char (typically '&') from a menu string. A double // accelerator char ('&&') will be converted to a single char. The out params // |accelerated_char_pos| and |accelerated_char_span| will be set to the index @@ -20,6 +22,11 @@ UI_EXPORT base::string16 RemoveAcceleratorChar(const base::string16& s, int* accelerated_char_pos, int* accelerated_char_span); +// Returns the number of horizontal pixels needed to display the specified +// |text| with |font_list|. +UI_EXPORT int GetStringWidth(const base::string16& text, + const FontList& font_list); + } // namespace gfx #endif // UI_GFX_TEXT_UTILS_H_ diff --git a/chromium/ui/gfx/text_utils_android.cc b/chromium/ui/gfx/text_utils_android.cc new file mode 100644 index 00000000000..c564b9b1db0 --- /dev/null +++ b/chromium/ui/gfx/text_utils_android.cc @@ -0,0 +1,16 @@ +// 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 "ui/gfx/text_utils.h" + +#include "base/logging.h" + +namespace gfx { + +int GetStringWidth(const base::string16& text, const FontList& font_list) { + NOTIMPLEMENTED(); + return 0; +} + +} // namespace gfx diff --git a/chromium/ui/gfx/text_utils_ios.mm b/chromium/ui/gfx/text_utils_ios.mm new file mode 100644 index 00000000000..1841864ff85 --- /dev/null +++ b/chromium/ui/gfx/text_utils_ios.mm @@ -0,0 +1,22 @@ +// 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 "ui/gfx/text_utils.h" + +#import <UIKit/UIKit.h> + +#include <cmath> + +#include "base/strings/sys_string_conversions.h" +#include "ui/gfx/font_list.h" + +namespace gfx { + +int GetStringWidth(const base::string16& text, const FontList& font_list) { + NSString* ns_text = base::SysUTF16ToNSString(text); + NativeFont native_font = font_list.GetPrimaryFont().GetNativeFont(); + return std::ceil([ns_text sizeWithFont:native_font].width); +} + +} // namespace gfx diff --git a/chromium/ui/gfx/text_utils_skia.cc b/chromium/ui/gfx/text_utils_skia.cc new file mode 100644 index 00000000000..0de1156a14b --- /dev/null +++ b/chromium/ui/gfx/text_utils_skia.cc @@ -0,0 +1,15 @@ +// 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 "ui/gfx/text_utils.h" + +#include "ui/gfx/canvas.h" + +namespace gfx { + +int GetStringWidth(const base::string16& text, const FontList& font_list) { + return Canvas::GetStringWidth(text, font_list); +} + +} // namespace gfx diff --git a/chromium/ui/gfx/transform.cc b/chromium/ui/gfx/transform.cc index c7bf91af411..5f8a36760d1 100644 --- a/chromium/ui/gfx/transform.cc +++ b/chromium/ui/gfx/transform.cc @@ -9,6 +9,7 @@ #include <cmath> +#include "base/logging.h" #include "base/strings/stringprintf.h" #include "ui/gfx/point.h" #include "ui/gfx/point3_f.h" @@ -23,61 +24,72 @@ namespace gfx { namespace { // Taken from SkMatrix44. -const double kEpsilon = 1e-8; +const SkMScalar kEpsilon = 1e-8; -double TanDegrees(double degrees) { - double radians = degrees * M_PI / 180; +SkMScalar TanDegrees(double degrees) { + SkMScalar radians = degrees * M_PI / 180; return std::tan(radians); } } // namespace -Transform::Transform( - double col1row1, double col2row1, double col3row1, double col4row1, - double col1row2, double col2row2, double col3row2, double col4row2, - double col1row3, double col2row3, double col3row3, double col4row3, - double col1row4, double col2row4, double col3row4, double col4row4) - : matrix_(SkMatrix44::kUninitialized_Constructor) -{ - matrix_.setDouble(0, 0, col1row1); - matrix_.setDouble(1, 0, col1row2); - matrix_.setDouble(2, 0, col1row3); - matrix_.setDouble(3, 0, col1row4); - - matrix_.setDouble(0, 1, col2row1); - matrix_.setDouble(1, 1, col2row2); - matrix_.setDouble(2, 1, col2row3); - matrix_.setDouble(3, 1, col2row4); - - matrix_.setDouble(0, 2, col3row1); - matrix_.setDouble(1, 2, col3row2); - matrix_.setDouble(2, 2, col3row3); - matrix_.setDouble(3, 2, col3row4); - - matrix_.setDouble(0, 3, col4row1); - matrix_.setDouble(1, 3, col4row2); - matrix_.setDouble(2, 3, col4row3); - matrix_.setDouble(3, 3, col4row4); -} - -Transform::Transform( - double col1row1, double col2row1, - double col1row2, double col2row2, - double x_translation, double y_translation) - : matrix_(SkMatrix44::kIdentity_Constructor) -{ - matrix_.setDouble(0, 0, col1row1); - matrix_.setDouble(1, 0, col1row2); - matrix_.setDouble(0, 1, col2row1); - matrix_.setDouble(1, 1, col2row2); - matrix_.setDouble(0, 3, x_translation); - matrix_.setDouble(1, 3, y_translation); +Transform::Transform(SkMScalar col1row1, + SkMScalar col2row1, + SkMScalar col3row1, + SkMScalar col4row1, + SkMScalar col1row2, + SkMScalar col2row2, + SkMScalar col3row2, + SkMScalar col4row2, + SkMScalar col1row3, + SkMScalar col2row3, + SkMScalar col3row3, + SkMScalar col4row3, + SkMScalar col1row4, + SkMScalar col2row4, + SkMScalar col3row4, + SkMScalar col4row4) + : matrix_(SkMatrix44::kUninitialized_Constructor) { + matrix_.set(0, 0, col1row1); + matrix_.set(1, 0, col1row2); + matrix_.set(2, 0, col1row3); + matrix_.set(3, 0, col1row4); + + matrix_.set(0, 1, col2row1); + matrix_.set(1, 1, col2row2); + matrix_.set(2, 1, col2row3); + matrix_.set(3, 1, col2row4); + + matrix_.set(0, 2, col3row1); + matrix_.set(1, 2, col3row2); + matrix_.set(2, 2, col3row3); + matrix_.set(3, 2, col3row4); + + matrix_.set(0, 3, col4row1); + matrix_.set(1, 3, col4row2); + matrix_.set(2, 3, col4row3); + matrix_.set(3, 3, col4row4); +} + +Transform::Transform(SkMScalar col1row1, + SkMScalar col2row1, + SkMScalar col1row2, + SkMScalar col2row2, + SkMScalar x_translation, + SkMScalar y_translation) + : matrix_(SkMatrix44::kIdentity_Constructor) { + matrix_.set(0, 0, col1row1); + matrix_.set(1, 0, col1row2); + matrix_.set(0, 1, col2row1); + matrix_.set(1, 1, col2row2); + matrix_.set(0, 3, x_translation); + matrix_.set(1, 3, y_translation); } void Transform::RotateAboutXAxis(double degrees) { double radians = degrees * M_PI / 180; - double cosTheta = std::cos(radians); - double sinTheta = std::sin(radians); + SkMScalar cosTheta = SkDoubleToMScalar(std::cos(radians)); + SkMScalar sinTheta = SkDoubleToMScalar(std::sin(radians)); if (matrix_.isIdentity()) { matrix_.set3x3(1, 0, 0, 0, cosTheta, sinTheta, @@ -93,8 +105,8 @@ void Transform::RotateAboutXAxis(double degrees) { void Transform::RotateAboutYAxis(double degrees) { double radians = degrees * M_PI / 180; - double cosTheta = std::cos(radians); - double sinTheta = std::sin(radians); + SkMScalar cosTheta = SkDoubleToMScalar(std::cos(radians)); + SkMScalar sinTheta = SkDoubleToMScalar(std::sin(radians)); if (matrix_.isIdentity()) { // Note carefully the placement of the -sinTheta for rotation about // y-axis is different than rotation about x-axis or z-axis. @@ -112,8 +124,8 @@ void Transform::RotateAboutYAxis(double degrees) { void Transform::RotateAboutZAxis(double degrees) { double radians = degrees * M_PI / 180; - double cosTheta = std::cos(radians); - double sinTheta = std::sin(radians); + SkMScalar cosTheta = SkDoubleToMScalar(std::cos(radians)); + SkMScalar sinTheta = SkDoubleToMScalar(std::sin(radians)); if (matrix_.isIdentity()) { matrix_.set3x3(cosTheta, sinTheta, 0, -sinTheta, cosTheta, 0, @@ -129,68 +141,62 @@ void Transform::RotateAboutZAxis(double degrees) { void Transform::RotateAbout(const Vector3dF& axis, double degrees) { if (matrix_.isIdentity()) { - matrix_.setRotateDegreesAbout(SkDoubleToMScalar(axis.x()), - SkDoubleToMScalar(axis.y()), - SkDoubleToMScalar(axis.z()), - SkDoubleToMScalar(degrees)); + matrix_.setRotateDegreesAbout(SkFloatToMScalar(axis.x()), + SkFloatToMScalar(axis.y()), + SkFloatToMScalar(axis.z()), + degrees); } else { SkMatrix44 rot(SkMatrix44::kUninitialized_Constructor); - rot.setRotateDegreesAbout(SkDoubleToMScalar(axis.x()), - SkDoubleToMScalar(axis.y()), - SkDoubleToMScalar(axis.z()), - SkDoubleToMScalar(degrees)); + rot.setRotateDegreesAbout(SkFloatToMScalar(axis.x()), + SkFloatToMScalar(axis.y()), + SkFloatToMScalar(axis.z()), + degrees); matrix_.preConcat(rot); } } -void Transform::Scale(double x, double y) { - matrix_.preScale(SkDoubleToMScalar(x), SkDoubleToMScalar(y), 1); -} +void Transform::Scale(SkMScalar x, SkMScalar y) { matrix_.preScale(x, y, 1); } -void Transform::Scale3d(double x, double y, double z) { - matrix_.preScale(SkDoubleToMScalar(x), - SkDoubleToMScalar(y), - SkDoubleToMScalar(z)); +void Transform::Scale3d(SkMScalar x, SkMScalar y, SkMScalar z) { + matrix_.preScale(x, y, z); } -void Transform::Translate(double x, double y) { - matrix_.preTranslate(SkDoubleToMScalar(x), SkDoubleToMScalar(y), 0); +void Transform::Translate(SkMScalar x, SkMScalar y) { + matrix_.preTranslate(x, y, 0); } -void Transform::Translate3d(double x, double y, double z) { - matrix_.preTranslate(SkDoubleToMScalar(x), - SkDoubleToMScalar(y), - SkDoubleToMScalar(z)); +void Transform::Translate3d(SkMScalar x, SkMScalar y, SkMScalar z) { + matrix_.preTranslate(x, y, z); } -void Transform::SkewX(double angle_x) { +void Transform::SkewX(SkMScalar angle_x) { if (matrix_.isIdentity()) - matrix_.setDouble(0, 1, TanDegrees(angle_x)); + matrix_.set(0, 1, TanDegrees(angle_x)); else { SkMatrix44 skew(SkMatrix44::kIdentity_Constructor); - skew.setDouble(0, 1, TanDegrees(angle_x)); + skew.set(0, 1, TanDegrees(angle_x)); matrix_.preConcat(skew); } } -void Transform::SkewY(double angle_y) { +void Transform::SkewY(SkMScalar angle_y) { if (matrix_.isIdentity()) - matrix_.setDouble(1, 0, TanDegrees(angle_y)); + matrix_.set(1, 0, TanDegrees(angle_y)); else { SkMatrix44 skew(SkMatrix44::kIdentity_Constructor); - skew.setDouble(1, 0, TanDegrees(angle_y)); + skew.set(1, 0, TanDegrees(angle_y)); matrix_.preConcat(skew); } } -void Transform::ApplyPerspectiveDepth(double depth) { +void Transform::ApplyPerspectiveDepth(SkMScalar depth) { if (depth == 0) return; if (matrix_.isIdentity()) - matrix_.setDouble(3, 2, -1.0 / depth); + matrix_.set(3, 2, -1.0 / depth); else { SkMatrix44 m(SkMatrix44::kIdentity_Constructor); - m.setDouble(3, 2, -1.0 / depth); + m.set(3, 2, -1.0 / depth); matrix_.preConcat(m); } } @@ -208,9 +214,9 @@ bool Transform::IsIdentityOrIntegerTranslation() const { return false; bool no_fractional_translation = - static_cast<int>(matrix_.getDouble(0, 3)) == matrix_.getDouble(0, 3) && - static_cast<int>(matrix_.getDouble(1, 3)) == matrix_.getDouble(1, 3) && - static_cast<int>(matrix_.getDouble(2, 3)) == matrix_.getDouble(2, 3); + static_cast<int>(matrix_.get(0, 3)) == matrix_.get(0, 3) && + static_cast<int>(matrix_.get(1, 3)) == matrix_.get(1, 3) && + static_cast<int>(matrix_.get(2, 3)) == matrix_.get(2, 3); return no_fractional_translation; } @@ -243,34 +249,22 @@ bool Transform::IsBackFaceVisible() const { // Compute the cofactor of the 3rd row, 3rd column. double cofactor_part_1 = - matrix_.getDouble(0, 0) * - matrix_.getDouble(1, 1) * - matrix_.getDouble(3, 3); + matrix_.get(0, 0) * matrix_.get(1, 1) * matrix_.get(3, 3); double cofactor_part_2 = - matrix_.getDouble(0, 1) * - matrix_.getDouble(1, 3) * - matrix_.getDouble(3, 0); + matrix_.get(0, 1) * matrix_.get(1, 3) * matrix_.get(3, 0); double cofactor_part_3 = - matrix_.getDouble(0, 3) * - matrix_.getDouble(1, 0) * - matrix_.getDouble(3, 1); + matrix_.get(0, 3) * matrix_.get(1, 0) * matrix_.get(3, 1); double cofactor_part_4 = - matrix_.getDouble(0, 0) * - matrix_.getDouble(1, 3) * - matrix_.getDouble(3, 1); + matrix_.get(0, 0) * matrix_.get(1, 3) * matrix_.get(3, 1); double cofactor_part_5 = - matrix_.getDouble(0, 1) * - matrix_.getDouble(1, 0) * - matrix_.getDouble(3, 3); + matrix_.get(0, 1) * matrix_.get(1, 0) * matrix_.get(3, 3); double cofactor_part_6 = - matrix_.getDouble(0, 3) * - matrix_.getDouble(1, 1) * - matrix_.getDouble(3, 0); + matrix_.get(0, 3) * matrix_.get(1, 1) * matrix_.get(3, 0); double cofactor33 = cofactor_part_1 + @@ -316,30 +310,30 @@ bool Transform::Preserves2dAxisAlignment() const { // values: The current implementation conservatively assumes that axis // alignment is not preserved. - bool has_x_or_y_perspective = matrix_.getDouble(3, 0) != 0 || - matrix_.getDouble(3, 1) != 0; + bool has_x_or_y_perspective = + matrix_.get(3, 0) != 0 || matrix_.get(3, 1) != 0; int num_non_zero_in_row_0 = 0; int num_non_zero_in_row_1 = 0; int num_non_zero_in_col_0 = 0; int num_non_zero_in_col_1 = 0; - if (std::abs(matrix_.getDouble(0, 0)) > kEpsilon) { + if (std::abs(matrix_.get(0, 0)) > kEpsilon) { num_non_zero_in_row_0++; num_non_zero_in_col_0++; } - if (std::abs(matrix_.getDouble(0, 1)) > kEpsilon) { + if (std::abs(matrix_.get(0, 1)) > kEpsilon) { num_non_zero_in_row_0++; num_non_zero_in_col_1++; } - if (std::abs(matrix_.getDouble(1, 0)) > kEpsilon) { + if (std::abs(matrix_.get(1, 0)) > kEpsilon) { num_non_zero_in_row_1++; num_non_zero_in_col_0++; } - if (std::abs(matrix_.getDouble(1, 1)) > kEpsilon) { + if (std::abs(matrix_.get(1, 1)) > kEpsilon) { num_non_zero_in_row_1++; num_non_zero_in_col_1++; } @@ -357,24 +351,33 @@ void Transform::Transpose() { } void Transform::FlattenTo2d() { - matrix_.setDouble(2, 0, 0.0); - matrix_.setDouble(2, 1, 0.0); - matrix_.setDouble(0, 2, 0.0); - matrix_.setDouble(1, 2, 0.0); - matrix_.setDouble(2, 2, 1.0); - matrix_.setDouble(3, 2, 0.0); - matrix_.setDouble(2, 3, 0.0); + matrix_.set(2, 0, 0.0); + matrix_.set(2, 1, 0.0); + matrix_.set(0, 2, 0.0); + matrix_.set(1, 2, 0.0); + matrix_.set(2, 2, 1.0); + matrix_.set(3, 2, 0.0); + matrix_.set(2, 3, 0.0); +} + +Vector2dF Transform::To2dTranslation() const { + return gfx::Vector2dF(SkMScalarToFloat(matrix_.get(0, 3)), + SkMScalarToFloat(matrix_.get(1, 3))); } -void Transform::TransformPoint(Point& point) const { +void Transform::TransformPoint(Point* point) const { + DCHECK(point); TransformPointInternal(matrix_, point); } -void Transform::TransformPoint(Point3F& point) const { +void Transform::TransformPoint(Point3F* point) const { + DCHECK(point); TransformPointInternal(matrix_, point); } -bool Transform::TransformPointReverse(Point& point) const { +bool Transform::TransformPointReverse(Point* point) const { + DCHECK(point); + // TODO(sad): Try to avoid trying to invert the matrix. SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor); if (!matrix_.invert(&inverse)) @@ -384,7 +387,9 @@ bool Transform::TransformPointReverse(Point& point) const { return true; } -bool Transform::TransformPointReverse(Point3F& point) const { +bool Transform::TransformPointReverse(Point3F* point) const { + DCHECK(point); + // TODO(sad): Try to avoid trying to invert the matrix. SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor); if (!matrix_.invert(&inverse)) @@ -419,7 +424,7 @@ bool Transform::TransformRectReverse(RectF* rect) const { return true; } -bool Transform::Blend(const Transform& from, double progress) { +bool Transform::Blend(const Transform& from, SkMScalar progress) { DecomposedTransform to_decomp; DecomposedTransform from_decomp; if (!DecomposeTransform(&to_decomp, *this) || @@ -434,41 +439,33 @@ bool Transform::Blend(const Transform& from, double progress) { } void Transform::TransformPointInternal(const SkMatrix44& xform, - Point3F& point) const { + Point3F* point) const { if (xform.isIdentity()) return; - SkMScalar p[4] = { - SkDoubleToMScalar(point.x()), - SkDoubleToMScalar(point.y()), - SkDoubleToMScalar(point.z()), - SkDoubleToMScalar(1) - }; + SkMScalar p[4] = {SkFloatToMScalar(point->x()), SkFloatToMScalar(point->y()), + SkFloatToMScalar(point->z()), 1}; xform.mapMScalars(p); if (p[3] != 1 && abs(p[3]) > 0) { - point.SetPoint(p[0] / p[3], p[1] / p[3], p[2]/ p[3]); + point->SetPoint(p[0] / p[3], p[1] / p[3], p[2]/ p[3]); } else { - point.SetPoint(p[0], p[1], p[2]); + point->SetPoint(p[0], p[1], p[2]); } } void Transform::TransformPointInternal(const SkMatrix44& xform, - Point& point) const { + Point* point) const { if (xform.isIdentity()) return; - SkMScalar p[4] = { - SkDoubleToMScalar(point.x()), - SkDoubleToMScalar(point.y()), - SkDoubleToMScalar(0), - SkDoubleToMScalar(1) - }; + SkMScalar p[4] = {SkFloatToMScalar(point->x()), SkFloatToMScalar(point->y()), + 0, 1}; xform.mapMScalars(p); - point.SetPoint(ToRoundedInt(p[0]), ToRoundedInt(p[1])); + point->SetPoint(ToRoundedInt(p[0]), ToRoundedInt(p[1])); } std::string Transform::ToString() const { @@ -477,22 +474,22 @@ std::string Transform::ToString() const { " %+0.4f %+0.4f %+0.4f %+0.4f \n" " %+0.4f %+0.4f %+0.4f %+0.4f \n" " %+0.4f %+0.4f %+0.4f %+0.4f ]\n", - matrix_.getDouble(0, 0), - matrix_.getDouble(0, 1), - matrix_.getDouble(0, 2), - matrix_.getDouble(0, 3), - matrix_.getDouble(1, 0), - matrix_.getDouble(1, 1), - matrix_.getDouble(1, 2), - matrix_.getDouble(1, 3), - matrix_.getDouble(2, 0), - matrix_.getDouble(2, 1), - matrix_.getDouble(2, 2), - matrix_.getDouble(2, 3), - matrix_.getDouble(3, 0), - matrix_.getDouble(3, 1), - matrix_.getDouble(3, 2), - matrix_.getDouble(3, 3)); + matrix_.get(0, 0), + matrix_.get(0, 1), + matrix_.get(0, 2), + matrix_.get(0, 3), + matrix_.get(1, 0), + matrix_.get(1, 1), + matrix_.get(1, 2), + matrix_.get(1, 3), + matrix_.get(2, 0), + matrix_.get(2, 1), + matrix_.get(2, 2), + matrix_.get(2, 3), + matrix_.get(3, 0), + matrix_.get(3, 1), + matrix_.get(3, 2), + matrix_.get(3, 3)); } } // namespace gfx diff --git a/chromium/ui/gfx/transform.h b/chromium/ui/gfx/transform.h index 66e76ea0514..8e51d7941be 100644 --- a/chromium/ui/gfx/transform.h +++ b/chromium/ui/gfx/transform.h @@ -9,7 +9,8 @@ #include "base/compiler_specific.h" #include "third_party/skia/include/utils/SkMatrix44.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" +#include "ui/gfx/vector2d_f.h" namespace gfx { @@ -39,16 +40,31 @@ class UI_EXPORT Transform { : matrix_(lhs.matrix_, rhs.matrix_) {} // Constructs a transform from explicit 16 matrix elements. Elements // should be given in row-major order. - Transform(double col1row1, double col2row1, double col3row1, double col4row1, - double col1row2, double col2row2, double col3row2, double col4row2, - double col1row3, double col2row3, double col3row3, double col4row3, - double col1row4, double col2row4, double col3row4, double col4row4); + Transform(SkMScalar col1row1, + SkMScalar col2row1, + SkMScalar col3row1, + SkMScalar col4row1, + SkMScalar col1row2, + SkMScalar col2row2, + SkMScalar col3row2, + SkMScalar col4row2, + SkMScalar col1row3, + SkMScalar col2row3, + SkMScalar col3row3, + SkMScalar col4row3, + SkMScalar col1row4, + SkMScalar col2row4, + SkMScalar col3row4, + SkMScalar col4row4); // Constructs a transform from explicit 2d elements. All other matrix // elements remain the same as the corresponding elements of an identity // matrix. - Transform(double col1row1, double col2row1, - double col1row2, double col2row2, - double x_translation, double y_translation); + Transform(SkMScalar col1row1, + SkMScalar col2row1, + SkMScalar col1row2, + SkMScalar col2row2, + SkMScalar x_translation, + SkMScalar y_translation); ~Transform() {} bool operator==(const Transform& rhs) const { return matrix_ == rhs.matrix_; } @@ -70,22 +86,22 @@ class UI_EXPORT Transform { // Applies the current transformation on a scaling and assigns the result // to |this|. - void Scale(double x, double y); - void Scale3d(double x, double y, double z); + void Scale(SkMScalar x, SkMScalar y); + void Scale3d(SkMScalar x, SkMScalar y, SkMScalar z); // Applies the current transformation on a translation and assigns the result // to |this|. - void Translate(double x, double y); - void Translate3d(double x, double y, double z); + void Translate(SkMScalar x, SkMScalar y); + void Translate3d(SkMScalar x, SkMScalar y, SkMScalar z); // Applies the current transformation on a skew and assigns the result // to |this|. - void SkewX(double angle_x); - void SkewY(double angle_y); + void SkewX(SkMScalar angle_x); + void SkewY(SkMScalar angle_y); // Applies the current transformation on a perspective transform and assigns // the result to |this|. - void ApplyPerspectiveDepth(double depth); + void ApplyPerspectiveDepth(SkMScalar depth); // Applies a transformation on the current transformation // (i.e. 'this = this * transform;'). @@ -107,9 +123,8 @@ class UI_EXPORT Transform { bool IsPositiveScaleOrTranslation() const { if (!IsScaleOrTranslation()) return false; - return matrix_.getDouble(0, 0) > 0.0 && - matrix_.getDouble(1, 1) > 0.0 && - matrix_.getDouble(2, 2) > 0.0; + return matrix_.get(0, 0) > 0.0 && matrix_.get(1, 1) > 0.0 && + matrix_.get(2, 2) > 0.0; } // Returns true if the matrix is either identity or pure, non-fractional @@ -161,21 +176,24 @@ class UI_EXPORT Transform { // void FlattenTo2d(); + // Returns the x and y translation components of the matrix. + Vector2dF To2dTranslation() const; + // Applies the transformation on the point. Returns true if the point is // transformed successfully. - void TransformPoint(Point3F& point) const; + void TransformPoint(Point3F* point) const; // Applies the transformation on the point. Returns true if the point is // transformed successfully. Rounds the result to the nearest point. - void TransformPoint(Point& point) const; + void TransformPoint(Point* point) const; // Applies the reverse transformation on the point. Returns true if the // transformation can be inverted. - bool TransformPointReverse(Point3F& point) const; + bool TransformPointReverse(Point3F* point) const; // Applies the reverse transformation on the point. Returns true if the // transformation can be inverted. Rounds the result to the nearest point. - bool TransformPointReverse(Point& point) const; + bool TransformPointReverse(Point* point) const; // Applies transformation on the rectangle. Returns true if the transformed // rectangle was axis aligned. If it returns false, rect will be the @@ -197,7 +215,7 @@ class UI_EXPORT Transform { // you're going to be calling this rapidly (e.g., in an animation) you should // decompose once using gfx::DecomposeTransforms and reuse your // DecomposedTransform. - bool Blend(const Transform& from, double progress); + bool Blend(const Transform& from, SkMScalar progress); // Returns |this| * |other|. Transform operator*(const Transform& other) const { @@ -218,10 +236,10 @@ class UI_EXPORT Transform { private: void TransformPointInternal(const SkMatrix44& xform, - Point& point) const; + Point* point) const; void TransformPointInternal(const SkMatrix44& xform, - Point3F& point) const; + Point3F* point) const; SkMatrix44 matrix_; diff --git a/chromium/ui/gfx/transform_unittest.cc b/chromium/ui/gfx/transform_unittest.cc index f56ca6dc887..4394af67896 100644 --- a/chromium/ui/gfx/transform_unittest.cc +++ b/chromium/ui/gfx/transform_unittest.cc @@ -207,7 +207,7 @@ TEST(XFormTest, ConcatTranslate) { xform = translation * xform; Point3F p1(value.x1, value.y1, 0); Point3F p2(value.x2, value.y2, 0); - xform.TransformPoint(p1); + xform.TransformPoint(&p1); if (value.tx == value.tx && value.ty == value.ty) { EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); @@ -236,7 +236,7 @@ TEST(XFormTest, ConcatScale) { xform = scale * xform; Point3F p1(value.before, value.before, 0); Point3F p2(value.after, value.after, 0); - xform.TransformPoint(p1); + xform.TransformPoint(&p1); if (value.scale == value.scale) { EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); } @@ -267,7 +267,7 @@ TEST(XFormTest, ConcatRotate) { xform = rotation * xform; Point3F p1(value.x1, value.y1, 0); Point3F p2(value.x2, value.y2, 0); - xform.TransformPoint(p1); + xform.TransformPoint(&p1); if (value.degrees == value.degrees) { EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); } @@ -312,11 +312,11 @@ TEST(XFormTest, SetTranslate) { break; } p0 = p1; - xform.TransformPoint(p1); + xform.TransformPoint(&p1); if (value.tx == value.tx && value.ty == value.ty) { EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); - xform.TransformPointReverse(p1); + xform.TransformPointReverse(&p1); EXPECT_TRUE(PointsAreNearlyEqual(p1, p0)); } } @@ -359,11 +359,11 @@ TEST(XFormTest, SetScale) { break; } p0 = p1; - xform.TransformPoint(p1); + xform.TransformPoint(&p1); if (value.s == value.s) { EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); if (value.s != 0.0f) { - xform.TransformPointReverse(p1); + xform.TransformPointReverse(&p1); EXPECT_TRUE(PointsAreNearlyEqual(p1, p0)); } } @@ -399,9 +399,9 @@ TEST(XFormTest, SetRotate) { xform.Rotate(value.degree); // just want to make sure that we don't crash in the case of NaN. if (value.degree == value.degree) { - xform.TransformPoint(p1); + xform.TransformPoint(&p1); EXPECT_TRUE(PointsAreNearlyEqual(p1, p2)); - xform.TransformPointReverse(p1); + xform.TransformPointReverse(&p1); EXPECT_TRUE(PointsAreNearlyEqual(p1, p0)); } } @@ -434,7 +434,7 @@ TEST(XFormTest, ConcatTranslate2D) { xform = translation * xform; Point p1(value.x1, value.y1); Point p2(value.x2, value.y2); - xform.TransformPoint(p1); + xform.TransformPoint(&p1); if (value.tx == value.tx && value.ty == value.ty) { EXPECT_EQ(p1.x(), p2.x()); @@ -464,7 +464,7 @@ TEST(XFormTest, ConcatScale2D) { xform = scale * xform; Point p1(value.before, value.before); Point p2(value.after, value.after); - xform.TransformPoint(p1); + xform.TransformPoint(&p1); if (value.scale == value.scale) { EXPECT_EQ(p1.x(), p2.x()); EXPECT_EQ(p1.y(), p2.y()); @@ -496,7 +496,7 @@ TEST(XFormTest, ConcatRotate2D) { xform = rotation * xform; Point p1(value.x1, value.y1); Point p2(value.x2, value.y2); - xform.TransformPoint(p1); + xform.TransformPoint(&p1); if (value.degrees == value.degrees) { EXPECT_EQ(p1.x(), p2.x()); EXPECT_EQ(p1.y(), p2.y()); @@ -545,12 +545,12 @@ TEST(XFormTest, SetTranslate2D) { break; } p0 = p1; - xform.TransformPoint(p1); + xform.TransformPoint(&p1); if (value.tx == value.tx && value.ty == value.ty) { EXPECT_EQ(p1.x(), p2.x()); EXPECT_EQ(p1.y(), p2.y()); - xform.TransformPointReverse(p1); + xform.TransformPointReverse(&p1); EXPECT_EQ(p1.x(), p0.x()); EXPECT_EQ(p1.y(), p0.y()); } @@ -600,12 +600,12 @@ TEST(XFormTest, SetScale2D) { break; } p0 = p1; - xform.TransformPoint(p1); + xform.TransformPoint(&p1); if (value.s == value.s) { EXPECT_EQ(p1.x(), p2.x()); EXPECT_EQ(p1.y(), p2.y()); if (value.s != 0.0f) { - xform.TransformPointReverse(p1); + xform.TransformPointReverse(&p1); EXPECT_EQ(p1.x(), p0.x()); EXPECT_EQ(p1.y(), p0.y()); } @@ -643,10 +643,10 @@ TEST(XFormTest, SetRotate2D) { xform.Rotate(value.degree + j * epsilon); // just want to make sure that we don't crash in the case of NaN. if (value.degree == value.degree) { - xform.TransformPoint(pt); + xform.TransformPoint(&pt); EXPECT_EQ(value.xprime, pt.x()); EXPECT_EQ(value.yprime, pt.y()); - xform.TransformPointReverse(pt); + xform.TransformPointReverse(&pt); EXPECT_EQ(pt.x(), value.x); EXPECT_EQ(pt.y(), value.y); } @@ -2293,10 +2293,10 @@ static bool EmpiricallyPreserves2dAxisAlignment(const Transform& transform) { PointF(p4.x(), p4.y())); EXPECT_TRUE(test_quad.IsRectilinear()); - transform.TransformPoint(p1); - transform.TransformPoint(p2); - transform.TransformPoint(p3); - transform.TransformPoint(p4); + transform.TransformPoint(&p1); + transform.TransformPoint(&p2); + transform.TransformPoint(&p3); + transform.TransformPoint(&p4); QuadF transformedQuad(PointF(p1.x(), p1.y()), PointF(p2.x(), p2.y()), @@ -2494,6 +2494,16 @@ TEST(XFormTest, Preserves2dAxisAlignment) { EXPECT_TRUE(transform.Preserves2dAxisAlignment()); } +TEST(XFormTest, To2dTranslation) { + Vector2dF translation(3.f, 7.f); + Transform transform; + transform.Translate(translation.x(), translation.y() + 1); + EXPECT_NE(translation.ToString(), transform.To2dTranslation().ToString()); + transform.MakeIdentity(); + transform.Translate(translation.x(), translation.y()); + EXPECT_EQ(translation.ToString(), transform.To2dTranslation().ToString()); +} + } // namespace } // namespace gfx diff --git a/chromium/ui/gfx/transform_util.cc b/chromium/ui/gfx/transform_util.cc index 90c8b56e554..9bb3bbcbcfb 100644 --- a/chromium/ui/gfx/transform_util.cc +++ b/chromium/ui/gfx/transform_util.cc @@ -4,6 +4,7 @@ #include "ui/gfx/transform_util.h" +#include <algorithm> #include <cmath> #include "ui/gfx/point.h" @@ -12,51 +13,51 @@ namespace gfx { namespace { -double Length3(double v[3]) { +SkMScalar Length3(SkMScalar v[3]) { return std::sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); } -void Scale3(double v[3], double scale) { +void Scale3(SkMScalar v[3], SkMScalar scale) { for (int i = 0; i < 3; ++i) v[i] *= scale; } template <int n> -double Dot(const double* a, const double* b) { - double toReturn = 0; +SkMScalar Dot(const SkMScalar* a, const SkMScalar* b) { + SkMScalar toReturn = 0; for (int i = 0; i < n; ++i) toReturn += a[i] * b[i]; return toReturn; } template <int n> -void Combine(double* out, - const double* a, - const double* b, - double scale_a, - double scale_b) { +void Combine(SkMScalar* out, + const SkMScalar* a, + const SkMScalar* b, + SkMScalar scale_a, + SkMScalar scale_b) { for (int i = 0; i < n; ++i) out[i] = a[i] * scale_a + b[i] * scale_b; } -void Cross3(double out[3], double a[3], double b[3]) { - double x = a[1] * b[2] - a[2] * b[1]; - double y = a[2] * b[0] - a[0] * b[2]; - double z = a[0] * b[1] - a[1] * b[0]; +void Cross3(SkMScalar out[3], SkMScalar a[3], SkMScalar b[3]) { + SkMScalar x = a[1] * b[2] - a[2] * b[1]; + SkMScalar y = a[2] * b[0] - a[0] * b[2]; + SkMScalar z = a[0] * b[1] - a[1] * b[0]; out[0] = x; out[1] = y; out[2] = z; } // Taken from http://www.w3.org/TR/css3-transforms/. -bool Slerp(double out[4], - const double q1[4], - const double q2[4], - double progress) { - double product = Dot<4>(q1, q2); +bool Slerp(SkMScalar out[4], + const SkMScalar q1[4], + const SkMScalar q2[4], + SkMScalar progress) { + SkMScalar product = Dot<4>(q1, q2); // Clamp product to -1.0 <= product <= 1.0. - product = std::min(std::max(product, -1.0), 1.0); + product = std::min(std::max(product, -SK_MScalar1), SK_MScalar1); // Interpolate angles along the shortest path. For example, to interpolate // between a 175 degree angle and a 185 degree angle, interpolate along the @@ -65,25 +66,25 @@ bool Slerp(double out[4], // the current W3C spec. Fixing the spec to match this approach is discussed // at: // http://lists.w3.org/Archives/Public/www-style/2013May/0131.html - double scale1 = 1.0; + SkMScalar scale1 = SK_MScalar1; if (product < 0) { product = -product; - scale1 = -1.0; + scale1 = -SK_MScalar1; } - const double epsilon = 1e-5; - if (std::abs(product - 1.0) < epsilon) { + const SkMScalar epsilon = 1e-5; + if (std::abs(product - SK_MScalar1) < epsilon) { for (int i = 0; i < 4; ++i) out[i] = q1[i]; return true; } - double denom = std::sqrt(1 - product * product); - double theta = std::acos(product); - double w = std::sin(progress * theta) * (1 / denom); + SkMScalar denom = std::sqrt(1 - product * product); + SkMScalar theta = std::acos(product); + SkMScalar w = std::sin(progress * theta) * (1 / denom); scale1 *= std::cos(progress * theta) - product * w; - double scale2 = w; + SkMScalar scale2 = w; Combine<4>(out, q1, q2, scale1, scale2); return true; @@ -91,14 +92,14 @@ bool Slerp(double out[4], // Returns false if the matrix cannot be normalized. bool Normalize(SkMatrix44& m) { - if (m.getDouble(3, 3) == 0.0) + if (m.get(3, 3) == 0.0) // Cannot normalize. return false; - double scale = 1.0 / m.getDouble(3, 3); + SkMScalar scale = 1.0 / m.get(3, 3); for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) - m.setDouble(i, j, m.getDouble(i, j) * scale); + m.set(i, j, m.get(i, j) * scale); return true; } @@ -125,9 +126,9 @@ DecomposedTransform::DecomposedTransform() { bool BlendDecomposedTransforms(DecomposedTransform* out, const DecomposedTransform& to, const DecomposedTransform& from, - double progress) { - double scalea = progress; - double scaleb = 1.0 - progress; + SkMScalar progress) { + SkMScalar scalea = progress; + SkMScalar scaleb = SK_MScalar1 - progress; Combine<3>(out->translate, to.translate, from.translate, scalea, scaleb); Combine<3>(out->scale, to.scale, from.scale, scalea, scaleb); Combine<3>(out->skew, to.skew, from.skew, scalea, scaleb); @@ -152,18 +153,17 @@ bool DecomposeTransform(DecomposedTransform* decomp, SkMatrix44 perspectiveMatrix = matrix; for (int i = 0; i < 3; ++i) - perspectiveMatrix.setDouble(3, i, 0.0); + perspectiveMatrix.set(3, i, 0.0); - perspectiveMatrix.setDouble(3, 3, 1.0); + perspectiveMatrix.set(3, 3, 1.0); // If the perspective matrix is not invertible, we are also unable to // decompose, so we'll bail early. Constant taken from SkMatrix44::invert. if (std::abs(perspectiveMatrix.determinant()) < 1e-8) return false; - if (matrix.getDouble(3, 0) != 0.0 || - matrix.getDouble(3, 1) != 0.0 || - matrix.getDouble(3, 2) != 0.0) { + if (matrix.get(3, 0) != 0.0 || matrix.get(3, 1) != 0.0 || + matrix.get(3, 2) != 0.0) { // rhs is the right hand side of the equation. SkMScalar rhs[4] = { matrix.get(3, 0), @@ -195,12 +195,12 @@ bool DecomposeTransform(DecomposedTransform* decomp, } for (int i = 0; i < 3; i++) - decomp->translate[i] = matrix.getDouble(i, 3); + decomp->translate[i] = matrix.get(i, 3); - double row[3][3]; + SkMScalar row[3][3]; for (int i = 0; i < 3; i++) for (int j = 0; j < 3; ++j) - row[i][j] = matrix.getDouble(j, i); + row[i][j] = matrix.get(j, i); // Compute X scale factor and normalize first row. decomp->scale[0] = Length3(row[0]); @@ -235,7 +235,7 @@ bool DecomposeTransform(DecomposedTransform* decomp, // At this point, the matrix (in rows) is orthonormal. // Check for a coordinate system flip. If the determinant // is -1, then negate the matrix and the scaling factors. - double pdum3[3]; + SkMScalar pdum3[3]; Cross3(pdum3, row[1], row[2]); if (Dot<3>(row[0], pdum3) < 0) { for (int i = 0; i < 3; i++) { @@ -268,16 +268,15 @@ bool DecomposeTransform(DecomposedTransform* decomp, Transform ComposeTransform(const DecomposedTransform& decomp) { SkMatrix44 matrix(SkMatrix44::kIdentity_Constructor); for (int i = 0; i < 4; i++) - matrix.setDouble(3, i, decomp.perspective[i]); + matrix.set(3, i, decomp.perspective[i]); - matrix.preTranslate(SkDoubleToMScalar(decomp.translate[0]), - SkDoubleToMScalar(decomp.translate[1]), - SkDoubleToMScalar(decomp.translate[2])); + matrix.preTranslate( + decomp.translate[0], decomp.translate[1], decomp.translate[2]); - double x = decomp.quaternion[0]; - double y = decomp.quaternion[1]; - double z = decomp.quaternion[2]; - double w = decomp.quaternion[3]; + SkMScalar x = decomp.quaternion[0]; + SkMScalar y = decomp.quaternion[1]; + SkMScalar z = decomp.quaternion[2]; + SkMScalar w = decomp.quaternion[3]; SkMatrix44 rotation_matrix(SkMatrix44::kUninitialized_Constructor); rotation_matrix.set3x3(1.0 - 2.0 * (y * y + z * z), @@ -294,25 +293,23 @@ Transform ComposeTransform(const DecomposedTransform& decomp) { SkMatrix44 temp(SkMatrix44::kIdentity_Constructor); if (decomp.skew[2]) { - temp.setDouble(1, 2, decomp.skew[2]); + temp.set(1, 2, decomp.skew[2]); matrix.preConcat(temp); } if (decomp.skew[1]) { - temp.setDouble(1, 2, 0); - temp.setDouble(0, 2, decomp.skew[1]); + temp.set(1, 2, 0); + temp.set(0, 2, decomp.skew[1]); matrix.preConcat(temp); } if (decomp.skew[0]) { - temp.setDouble(0, 2, 0); - temp.setDouble(0, 1, decomp.skew[0]); + temp.set(0, 2, 0); + temp.set(0, 1, decomp.skew[0]); matrix.preConcat(temp); } - matrix.preScale(SkDoubleToMScalar(decomp.scale[0]), - SkDoubleToMScalar(decomp.scale[1]), - SkDoubleToMScalar(decomp.scale[2])); + matrix.preScale(decomp.scale[0], decomp.scale[1], decomp.scale[2]); Transform to_return; to_return.matrix() = matrix; diff --git a/chromium/ui/gfx/transform_util.h b/chromium/ui/gfx/transform_util.h index b6da7b0782d..be5ba4c03ce 100644 --- a/chromium/ui/gfx/transform_util.h +++ b/chromium/ui/gfx/transform_util.h @@ -5,7 +5,7 @@ #ifndef UI_GFX_TRANSFORM_UTIL_H_ #define UI_GFX_TRANSFORM_UTIL_H_ -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/transform.h" namespace gfx { @@ -22,11 +22,11 @@ struct UI_EXPORT DecomposedTransform { // if used with Compose below, will produce the identity transform. DecomposedTransform(); - double translate[3]; - double scale[3]; - double skew[3]; - double perspective[4]; - double quaternion[4]; + SkMScalar translate[3]; + SkMScalar scale[3]; + SkMScalar skew[3]; + SkMScalar perspective[4]; + SkMScalar quaternion[4]; // Copy and assign are allowed. }; @@ -38,7 +38,7 @@ struct UI_EXPORT DecomposedTransform { UI_EXPORT bool BlendDecomposedTransforms(DecomposedTransform* out, const DecomposedTransform& to, const DecomposedTransform& from, - double progress); + SkMScalar progress); // Decomposes this transform into its translation, scale, skew, perspective, // and rotation components following the routines detailed in this spec: diff --git a/chromium/ui/gfx/transform_util_unittest.cc b/chromium/ui/gfx/transform_util_unittest.cc index 01ddbe538d0..94195c29bb9 100644 --- a/chromium/ui/gfx/transform_util_unittest.cc +++ b/chromium/ui/gfx/transform_util_unittest.cc @@ -21,7 +21,7 @@ TEST(TransformUtilTest, GetScaleTransform) { for (int sign_y = -1; sign_y <= 1; ++sign_y) { Point test(kAnchor.x() + sign_x * kOffset, kAnchor.y() + sign_y * kOffset); - scale.TransformPoint(test); + scale.TransformPoint(&test); EXPECT_EQ(Point(kAnchor.x() + sign_x * kOffset * kScale, kAnchor.y() + sign_y * kOffset * kScale), diff --git a/chromium/ui/base/text/utf16_indexing.cc b/chromium/ui/gfx/utf16_indexing.cc index d217f5d75c4..6af10c18499 100644 --- a/chromium/ui/base/text/utf16_indexing.cc +++ b/chromium/ui/gfx/utf16_indexing.cc @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/text/utf16_indexing.h" +#include "ui/gfx/utf16_indexing.h" #include "base/logging.h" #include "base/third_party/icu/icu_utf.h" -namespace ui { +namespace gfx { bool IsValidCodePointIndex(const string16& s, size_t index) { return index == 0 || index == s.length() || @@ -52,4 +52,4 @@ size_t UTF16OffsetToIndex(const string16& s, size_t base, ptrdiff_t offset) { return pos; } -} // namespace ui +} // namespace gfx diff --git a/chromium/ui/base/text/utf16_indexing.h b/chromium/ui/gfx/utf16_indexing.h index a1af3d9acd8..7f56384299f 100644 --- a/chromium/ui/base/text/utf16_indexing.h +++ b/chromium/ui/gfx/utf16_indexing.h @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_TEXT_UTF16_INDEXING_H_ -#define UI_BASE_TEXT_UTF16_INDEXING_H_ +#ifndef UI_GFX_UTF16_INDEXING_H_ +#define UI_GFX_UTF16_INDEXING_H_ #include "base/strings/string16.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" -namespace ui { +namespace gfx { // Returns false if s[index-1] is a high surrogate and s[index] is a low // surrogate, true otherwise. @@ -44,6 +44,6 @@ UI_EXPORT size_t UTF16OffsetToIndex(const string16& s, size_t base, ptrdiff_t offset); -} // namespace ui +} // namespace gfx -#endif // UI_BASE_TEXT_UTF16_INDEXING_H_ +#endif // UI_GFX_UTF16_INDEXING_H_ diff --git a/chromium/ui/base/text/utf16_indexing_unittest.cc b/chromium/ui/gfx/utf16_indexing_unittest.cc index 1bf8c30dbce..da2f8f5b56c 100644 --- a/chromium/ui/base/text/utf16_indexing_unittest.cc +++ b/chromium/ui/gfx/utf16_indexing_unittest.cc @@ -3,9 +3,9 @@ // found in the LICENSE file. #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/text/utf16_indexing.h" +#include "ui/gfx/utf16_indexing.h" -namespace ui { +namespace gfx { TEST(UTF16IndexingTest, IndexOffsetConversions) { // Valid surrogate pair surrounded by unpaired surrogates @@ -29,4 +29,4 @@ TEST(UTF16IndexingTest, IndexOffsetConversions) { } } -} // namespace ui +} // namespace gfx diff --git a/chromium/ui/gfx/vector2d.h b/chromium/ui/gfx/vector2d.h index 69f6b400ce3..9494120d26d 100644 --- a/chromium/ui/gfx/vector2d.h +++ b/chromium/ui/gfx/vector2d.h @@ -13,7 +13,7 @@ #include <string> #include "base/basictypes.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/vector2d_f.h" namespace gfx { diff --git a/chromium/ui/gfx/vector2d_f.h b/chromium/ui/gfx/vector2d_f.h index 4faf28ae226..ebd0b5b4fb5 100644 --- a/chromium/ui/gfx/vector2d_f.h +++ b/chromium/ui/gfx/vector2d_f.h @@ -12,7 +12,7 @@ #include <string> -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" namespace gfx { diff --git a/chromium/ui/gfx/vector3d_f.h b/chromium/ui/gfx/vector3d_f.h index 17ad332f3aa..aaa415b53bd 100644 --- a/chromium/ui/gfx/vector3d_f.h +++ b/chromium/ui/gfx/vector3d_f.h @@ -12,7 +12,7 @@ #include <string> -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/vector2d_f.h" namespace gfx { diff --git a/chromium/ui/base/win/dpi.cc b/chromium/ui/gfx/win/dpi.cc index 63804594d8e..98d23bd5ef9 100644 --- a/chromium/ui/base/win/dpi.cc +++ b/chromium/ui/gfx/win/dpi.cc @@ -2,15 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/win/dpi.h" +#include "ui/gfx/win/dpi.h" #include <windows.h> #include "base/command_line.h" #include "base/win/scoped_hdc.h" +#include "base/win/windows_version.h" #include "ui/base/layout.h" #include "base/win/registry.h" -#include "ui/base/ui_base_switches.h" #include "ui/gfx/display.h" +#include "ui/gfx/switches.h" #include "ui/gfx/point_conversions.h" #include "ui/gfx/rect_conversions.h" #include "ui/gfx/size_conversions.h" @@ -23,7 +24,8 @@ int kDefaultDPIY = 96; // Tests to see if the command line flag "--high-dpi-support" is set. bool IsHighDPIEnabled() { // Default is disabled. - if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kHighDPISupport)) { + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kHighDPISupport)) { return CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kHighDPISupport).compare("1") == 0; } @@ -36,7 +38,7 @@ bool IsHighDPIEnabled() { float GetDeviceScaleFactorImpl() { if (IsHighDPIEnabled()) { float scale = gfx::Display::HasForceDeviceScaleFactor() ? - gfx::Display::GetForcedDeviceScaleFactor() : ui::GetDPIScale(); + gfx::Display::GetForcedDeviceScaleFactor() : gfx::GetDPIScale(); // Quantize to nearest supported scale factor. scale = ui::GetScaleFactorScale(ui::GetScaleFactorFromScale(scale)); return scale; @@ -56,9 +58,9 @@ BOOL IsProcessDPIAwareWrapper() { } // namespace -namespace ui { +namespace gfx { -gfx::Size GetDPI() { +Size GetDPI() { static int dpi_x = 0; static int dpi_y = 0; static bool should_initialize = true; @@ -72,7 +74,7 @@ gfx::Size GetDPI() { dpi_x = GetDeviceCaps(screen_dc, LOGPIXELSX); dpi_y = GetDeviceCaps(screen_dc, LOGPIXELSY); } - return gfx::Size(dpi_x, dpi_y); + return Size(dpi_x, dpi_y); } float GetDPIScale() { @@ -106,35 +108,33 @@ float GetDeviceScaleFactor() { return device_scale_factor; } -gfx::Point ScreenToDIPPoint(const gfx::Point& pixel_point) { - return gfx::ToFlooredPoint( - gfx::ScalePoint(pixel_point, 1.0f / GetDeviceScaleFactor())); +Point ScreenToDIPPoint(const Point& pixel_point) { + return ToFlooredPoint(ScalePoint(pixel_point, 1.0f / GetDeviceScaleFactor())); } -gfx::Point DIPToScreenPoint(const gfx::Point& dip_point) { - return gfx::ToFlooredPoint( - gfx::ScalePoint(dip_point, GetDeviceScaleFactor())); +Point DIPToScreenPoint(const Point& dip_point) { + return ToFlooredPoint(ScalePoint(dip_point, GetDeviceScaleFactor())); } -gfx::Rect ScreenToDIPRect(const gfx::Rect& pixel_bounds) { +Rect ScreenToDIPRect(const Rect& pixel_bounds) { // TODO(kevers): Switch to non-deprecated method for float to int conversions. - return gfx::ToFlooredRectDeprecated( - gfx::ScaleRect(pixel_bounds, 1.0f / GetDeviceScaleFactor())); + return ToFlooredRectDeprecated( + ScaleRect(pixel_bounds, 1.0f / GetDeviceScaleFactor())); } -gfx::Rect DIPToScreenRect(const gfx::Rect& dip_bounds) { +Rect DIPToScreenRect(const Rect& dip_bounds) { // TODO(kevers): Switch to non-deprecated method for float to int conversions. - return gfx::ToFlooredRectDeprecated( - gfx::ScaleRect(dip_bounds, GetDeviceScaleFactor())); + return ToFlooredRectDeprecated( + ScaleRect(dip_bounds, GetDeviceScaleFactor())); } -gfx::Size ScreenToDIPSize(const gfx::Size& size_in_pixels) { - return gfx::ToFlooredSize( - gfx::ScaleSize(size_in_pixels, 1.0f / GetDeviceScaleFactor())); +Size ScreenToDIPSize(const Size& size_in_pixels) { + return ToFlooredSize( + ScaleSize(size_in_pixels, 1.0f / GetDeviceScaleFactor())); } -gfx::Size DIPToScreenSize(const gfx::Size& dip_size) { - return gfx::ToFlooredSize(gfx::ScaleSize(dip_size, GetDeviceScaleFactor())); +Size DIPToScreenSize(const Size& dip_size) { + return ToFlooredSize(ScaleSize(dip_size, GetDeviceScaleFactor())); } int GetSystemMetricsInDIP(int metric) { @@ -162,6 +162,14 @@ double GetUndocumentedDPIScale() { return scale; } -} // namespace win -} // namespace ui +double GetUndocumentedDPITouchScale() { + static double scale = + (base::win::GetVersion() < base::win::VERSION_WIN8_1) ? + GetUndocumentedDPIScale() : 1.0; + return scale; +} + + +} // namespace win +} // namespace gfx diff --git a/chromium/ui/base/win/dpi.h b/chromium/ui/gfx/win/dpi.h index 90edc7ca397..a056f532661 100644 --- a/chromium/ui/base/win/dpi.h +++ b/chromium/ui/gfx/win/dpi.h @@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_WIN_DPI_H_ -#define UI_BASE_WIN_DPI_H_ +#ifndef UI_GFX_DPI_WIN_H_ +#define UI_GFX_DPI_WIN_H_ +#include "ui/gfx/gfx_export.h" #include "ui/gfx/point.h" #include "ui/gfx/rect.h" #include "ui/gfx/size.h" -#include "ui/base/ui_export.h" -namespace ui { +namespace gfx { -UI_EXPORT gfx::Size GetDPI(); +UI_EXPORT Size GetDPI(); // Gets the scale factor of the display. For example, if the display DPI is // 96 then the scale factor is 1.0. @@ -28,31 +28,36 @@ namespace win { UI_EXPORT float GetDeviceScaleFactor(); -UI_EXPORT gfx::Point ScreenToDIPPoint(const gfx::Point& pixel_point); +UI_EXPORT Point ScreenToDIPPoint(const Point& pixel_point); -UI_EXPORT gfx::Point DIPToScreenPoint(const gfx::Point& dip_point); +UI_EXPORT Point DIPToScreenPoint(const Point& dip_point); -UI_EXPORT gfx::Rect ScreenToDIPRect(const gfx::Rect& pixel_bounds); +UI_EXPORT Rect ScreenToDIPRect(const Rect& pixel_bounds); -UI_EXPORT gfx::Rect DIPToScreenRect(const gfx::Rect& dip_bounds); +UI_EXPORT Rect DIPToScreenRect(const Rect& dip_bounds); -UI_EXPORT gfx::Size ScreenToDIPSize(const gfx::Size& size_in_pixels); +UI_EXPORT Size ScreenToDIPSize(const Size& size_in_pixels); -UI_EXPORT gfx::Size DIPToScreenSize(const gfx::Size& dip_size); +UI_EXPORT Size DIPToScreenSize(const Size& dip_size); // Win32's GetSystemMetrics uses pixel measures. This function calls // GetSystemMetrics for the given |metric|, then converts the result to DIP. UI_EXPORT int GetSystemMetricsInDIP(int metric); -// The OS secretly scales apps that are not DPIAware. This is not visible -// through standard OS calls like GetWindowPos(), or through GetDPIScale(). +// Sometimes the OS secretly scales apps that are not DPIAware. This is not +// visible through standard OS calls like GetWindowPos(), or through +// GetDPIScale(). // Returns the scale factor of the display, where 96 DPI is 1.0. // (Avoid this function... use GetDPIScale() instead.) // TODO(girard): Remove this once DPIAware is enabled - http://crbug.com/149881 UI_EXPORT double GetUndocumentedDPIScale(); -} // namespace win +// Win7 and Win8 send touch events scaled according to the current DPI +// scaling. Win8.1 corrects this, and sends touch events in DPI units. +// This function returns the appropriate scaling factor for touch events. +UI_EXPORT double GetUndocumentedDPITouchScale(); -} // namespace ui +} // namespace win +} // namespace gfx -#endif // UI_BASE_WIN_DPI_H_ +#endif // UI_GFX_DPI_WIN_H_ diff --git a/chromium/ui/base/win/hwnd_util.cc b/chromium/ui/gfx/win/hwnd_util.cc index 7299c8cd32d..91f0ddd182a 100644 --- a/chromium/ui/base/win/hwnd_util.cc +++ b/chromium/ui/gfx/win/hwnd_util.cc @@ -2,16 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/win/hwnd_util.h" +#include "ui/gfx/win/hwnd_util.h" #include "base/i18n/rtl.h" #include "base/strings/string_util.h" #include "base/win/metro.h" +#include "base/win/win_util.h" #include "ui/gfx/point.h" #include "ui/gfx/rect.h" #include "ui/gfx/size.h" -namespace ui { +namespace gfx { namespace { @@ -23,10 +24,10 @@ void AdjustWindowToFit(HWND hwnd, const RECT& bounds, bool fit_to_monitor) { if (hmon) { MONITORINFO mi; mi.cbSize = sizeof(mi); - GetMonitorInfo(hmon, &mi); - gfx::Rect window_rect(bounds); - gfx::Rect monitor_rect(mi.rcWork); - gfx::Rect new_window_rect = window_rect; + base::win::GetMonitorInfoWrapper(hmon, &mi); + Rect window_rect(bounds); + Rect monitor_rect(mi.rcWork); + Rect new_window_rect = window_rect; new_window_rect.AdjustToFit(monitor_rect); if (new_window_rect != window_rect) { // Window doesn't fit on monitor, move and possibly resize. @@ -114,7 +115,7 @@ bool DoesWindowBelongToActiveWindow(HWND window) { void CenterAndSizeWindow(HWND parent, HWND window, - const gfx::Size& pref) { + const Size& pref) { DCHECK(window && pref.width() > 0 && pref.height() > 0); // Calculate the ideal bounds. @@ -131,7 +132,7 @@ void CenterAndSizeWindow(HWND parent, if (monitor) { MONITORINFO mi = {0}; mi.cbSize = sizeof(mi); - GetMonitorInfo(monitor, &mi); + base::win::GetMonitorInfoWrapper(monitor, &mi); center_bounds = mi.rcWork; } else { NOTREACHED() << "Unable to get default monitor"; @@ -176,13 +177,13 @@ void CheckWindowCreated(HWND hwnd) { void ShowSystemMenu(HWND window) { RECT rect; GetWindowRect(window, &rect); - gfx::Point point = gfx::Point(rect.left, rect.top); + Point point = Point(rect.left, rect.top); static const int kSystemMenuOffset = 10; point.Offset(kSystemMenuOffset, kSystemMenuOffset); ShowSystemMenuAtPoint(window, point); } -void ShowSystemMenuAtPoint(HWND window, const gfx::Point& point) { +void ShowSystemMenuAtPoint(HWND window, const Point& point) { // In the Metro process, we never want to show the system menu. if (base::win::IsMetroProcess()) return; @@ -210,4 +211,4 @@ HWND GetWindowToParentTo(bool get_real_hwnd) { return root_window(); } -} // namespace ui +} // namespace gfx diff --git a/chromium/ui/base/win/hwnd_util.h b/chromium/ui/gfx/win/hwnd_util.h index ece1d3c5b65..70e5f8f1c2b 100644 --- a/chromium/ui/base/win/hwnd_util.h +++ b/chromium/ui/gfx/win/hwnd_util.h @@ -2,20 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_WIN_HWND_UTIL_H_ -#define UI_BASE_WIN_HWND_UTIL_H_ +#ifndef UI_GFX_WIN_HWND_UTIL_H_ +#define UI_GFX_WIN_HWND_UTIL_H_ #include <windows.h> #include "base/strings/string16.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" namespace gfx { class Point; class Size; -} - -namespace ui { // A version of the GetClassNameW API that returns the class name in an // string16. An empty result indicates a failure to get the class name. @@ -52,6 +49,6 @@ UI_EXPORT void ShowSystemMenuAtPoint(HWND window, const gfx::Point& point); // container so in those cases you should pass true in |get_real_hwnd|. UI_EXPORT HWND GetWindowToParentTo(bool get_real_hwnd); -} // namespace ui +} // namespace gfx -#endif // UI_BASE_WIN_HWND_UTIL_H_ +#endif // UI_GFX_WIN_HWND_UTIL_H_ diff --git a/chromium/ui/base/win/scoped_set_map_mode.h b/chromium/ui/gfx/win/scoped_set_map_mode.h index bf2b78dca5c..910837d109c 100644 --- a/chromium/ui/base/win/scoped_set_map_mode.h +++ b/chromium/ui/gfx/win/scoped_set_map_mode.h @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_WIN_SCOPED_SET_MAP_MODE_H_ -#define UI_BASE_WIN_SCOPED_SET_MAP_MODE_H_ +#ifndef UI_GFX_WIN_SCOPED_SET_MAP_MODE_H_ +#define UI_GFX_WIN_SCOPED_SET_MAP_MODE_H_ #include <windows.h> #include "base/basictypes.h" #include "base/logging.h" -namespace ui { +namespace gfx { // Helper class for setting and restore the map mode on a DC. class ScopedSetMapMode { @@ -35,6 +35,6 @@ class ScopedSetMapMode { DISALLOW_COPY_AND_ASSIGN(ScopedSetMapMode); }; -} // namespace ui +} // namespace gfx -#endif // UI_BASE_WIN_SCOPED_SET_MAP_MODE_H_ +#endif // UI_GFX_WIN_SCOPED_SET_MAP_MODE_H_ diff --git a/chromium/ui/base/win/singleton_hwnd.cc b/chromium/ui/gfx/win/singleton_hwnd.cc index 9d1685f4977..37993e8f4f0 100644 --- a/chromium/ui/base/win/singleton_hwnd.cc +++ b/chromium/ui/gfx/win/singleton_hwnd.cc @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/win/singleton_hwnd.h" +#include "ui/gfx/win/singleton_hwnd.h" #include "base/memory/singleton.h" #include "base/message_loop/message_loop.h" -namespace ui { +namespace gfx { // static SingletonHwnd* SingletonHwnd::GetInstance() { @@ -23,7 +23,7 @@ void SingletonHwnd::AddObserver(Observer* observer) { DLOG(ERROR) << "Cannot create windows on non-UI thread!"; return; } - WindowImpl::Init(NULL, gfx::Rect()); + WindowImpl::Init(NULL, Rect()); } observer_list_.AddObserver(observer); } @@ -52,4 +52,4 @@ SingletonHwnd::SingletonHwnd() { SingletonHwnd::~SingletonHwnd() { } -} // namespace ui +} // namespace gfx diff --git a/chromium/ui/base/win/singleton_hwnd.h b/chromium/ui/gfx/win/singleton_hwnd.h index a84b6c0b19b..96af6e79205 100644 --- a/chromium/ui/base/win/singleton_hwnd.h +++ b/chromium/ui/gfx/win/singleton_hwnd.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_WIN_SINGLETON_HWND_H_ -#define UI_BASE_WIN_SINGLETON_HWND_H_ +#ifndef UI_GFX_WIN_SINGLETON_HWND_H_ +#define UI_GFX_WIN_SINGLETON_HWND_H_ #include <windows.h> #include <vector> @@ -11,11 +11,11 @@ #include "base/basictypes.h" #include "base/callback_forward.h" #include "base/observer_list.h" -#include "ui/base/win/window_impl.h" +#include "ui/gfx/win/window_impl.h" template<typename T> struct DefaultSingletonTraits; -namespace ui { +namespace gfx { // Singleton message-only HWND that allows interested clients to receive WM_* // notifications. @@ -56,6 +56,6 @@ class SingletonHwnd : public WindowImpl { DISALLOW_COPY_AND_ASSIGN(SingletonHwnd); }; -} // namespace ui +} // namespace gfx -#endif // UI_BASE_WIN_SINGLETON_HWND_H_ +#endif // UI_GFX_WIN_SINGLETON_HWND_H_ diff --git a/chromium/ui/base/win/window_impl.cc b/chromium/ui/gfx/win/window_impl.cc index f53b1bf57ef..e2e6af05c61 100644 --- a/chromium/ui/base/win/window_impl.cc +++ b/chromium/ui/gfx/win/window_impl.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/win/window_impl.h" +#include "ui/gfx/win/window_impl.h" #include <list> @@ -11,9 +11,9 @@ #include "base/strings/string_number_conversions.h" #include "base/synchronization/lock.h" #include "base/win/wrapped_window_proc.h" -#include "ui/base/win/hwnd_util.h" +#include "ui/gfx/win/hwnd_util.h" -namespace ui { +namespace gfx { static const DWORD kWindowDefaultChildStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; @@ -100,7 +100,6 @@ ATOM ClassRegistrar::RetrieveClassAtom(const ClassInfo& class_info) { string16 name = string16(WindowImpl::kBaseClassName) + base::IntToString16(registered_count_++); - HBRUSH background = NULL; WNDCLASSEX window_class; base::win::InitializeWindowClass( name.c_str(), @@ -109,7 +108,7 @@ ATOM ClassRegistrar::RetrieveClassAtom(const ClassInfo& class_info) { 0, 0, NULL, - reinterpret_cast<HBRUSH>(background + 1), + NULL, NULL, class_info.icon, class_info.icon, @@ -150,7 +149,7 @@ WindowImpl::~WindowImpl() { ClearUserData(); } -void WindowImpl::Init(HWND parent, const gfx::Rect& bounds) { +void WindowImpl::Init(HWND parent, const Rect& bounds) { if (window_style_ == 0) window_style_ = parent ? kWindowDefaultChildStyle : kWindowDefaultStyle; @@ -217,7 +216,7 @@ void WindowImpl::Init(HWND parent, const gfx::Rect& bounds) { CheckWindowCreated(hwnd_); // The window procedure should have set the data for us. - CHECK_EQ(this, ui::GetWindowUserData(hwnd)); + CHECK_EQ(this, GetWindowUserData(hwnd)); } HICON WindowImpl::GetDefaultWindowIcon() const { @@ -237,7 +236,7 @@ LRESULT WindowImpl::OnWndProc(UINT message, WPARAM w_param, LPARAM l_param) { void WindowImpl::ClearUserData() { if (::IsWindow(hwnd_)) - ui::SetWindowUserData(hwnd_, NULL); + gfx::SetWindowUserData(hwnd_, NULL); } // static @@ -249,7 +248,7 @@ LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd, CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(l_param); WindowImpl* window = reinterpret_cast<WindowImpl*>(cs->lpCreateParams); DCHECK(window); - ui::SetWindowUserData(hwnd, window); + gfx::SetWindowUserData(hwnd, window); window->hwnd_ = hwnd; window->got_create_ = true; if (hwnd) @@ -257,8 +256,7 @@ LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd, return TRUE; } - WindowImpl* window = reinterpret_cast<WindowImpl*>( - ui::GetWindowUserData(hwnd)); + WindowImpl* window = reinterpret_cast<WindowImpl*>(GetWindowUserData(hwnd)); if (!window) return 0; @@ -271,4 +269,4 @@ ATOM WindowImpl::GetWindowClassAtom() { return ClassRegistrar::GetInstance()->RetrieveClassAtom(class_info); } -} // namespace ui +} // namespace gfx diff --git a/chromium/ui/base/win/window_impl.h b/chromium/ui/gfx/win/window_impl.h index 1f3b5d3cf88..2b0018e3f46 100644 --- a/chromium/ui/base/win/window_impl.h +++ b/chromium/ui/gfx/win/window_impl.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_WIN_WINDOW_IMPL_H_ -#define UI_BASE_WIN_WINDOW_IMPL_H_ +#ifndef UI_GFX_WIN_WINDOW_IMPL_H_ +#define UI_GFX_WIN_WINDOW_IMPL_H_ #include <atlbase.h> #include <atlapp.h> @@ -13,11 +13,11 @@ #include <string> #include "base/logging.h" -#include "ui/base/ui_export.h" +#include "ui/gfx/gfx_export.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/rect.h" -namespace ui { +namespace gfx { // An interface implemented by classes that use message maps. // ProcessWindowMessage is implemented by the BEGIN_MESSAGE_MAP_EX macro. @@ -118,6 +118,6 @@ class UI_EXPORT WindowImpl : public MessageMapInterface { DISALLOW_COPY_AND_ASSIGN(WindowImpl); }; -} // namespace ui +} // namespace gfx -#endif // UI_BASE_WIN_WINDOW_IMPL_H_ +#endif // UI_GFX_WIN_WINDOW_IMPL_H_ diff --git a/chromium/ui/gfx/x/x11_types.cc b/chromium/ui/gfx/x/x11_types.cc new file mode 100644 index 00000000000..c47c852527b --- /dev/null +++ b/chromium/ui/gfx/x/x11_types.cc @@ -0,0 +1,16 @@ +// Copyright (c) 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 "ui/gfx/x/x11_types.h" + +#include "base/message_loop/message_loop.h" + +namespace gfx { + +XDisplay* GetXDisplay() { + return base::MessagePumpForUI::GetDefaultXDisplay(); +} + +} // namespace gfx + diff --git a/chromium/ui/gfx/x/x11_types.h b/chromium/ui/gfx/x/x11_types.h new file mode 100644 index 00000000000..eab42f2352b --- /dev/null +++ b/chromium/ui/gfx/x/x11_types.h @@ -0,0 +1,25 @@ +// Copyright (c) 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. + +#ifndef UI_GFX_X_X11_UTIL_H_ +#define UI_GFX_X_X11_UTIL_H_ + +#include "ui/gfx/gfx_export.h" + +typedef unsigned long XID; +typedef struct _XImage XImage; +typedef struct _XGC *GC; +typedef struct _XDisplay XDisplay; + +namespace gfx { + +// TODO(oshima|evan): This assume there is one display and doesn't work +// undef multiple displays/monitor environment. Remove this and change the +// chrome codebase to get the display from window. +GFX_EXPORT XDisplay* GetXDisplay(); + +} // namespace gfx + +#endif // UI_GFX_X_X11_UTIL_H_ + diff --git a/chromium/ui/gl/android/gl_jni_registrar.cc b/chromium/ui/gl/android/gl_jni_registrar.cc deleted file mode 100644 index cba90cef77d..00000000000 --- a/chromium/ui/gl/android/gl_jni_registrar.cc +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 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 "ui/gl/android/gl_jni_registrar.h" - -#include "base/android/jni_android.h" -#include "base/android/jni_registrar.h" -#include "ui/gl/android/surface_texture_bridge.h" -#include "ui/gl/android/surface_texture_listener.h" - -namespace ui { -namespace gl { -namespace android { - -static base::android::RegistrationMethod kGLRegisteredMethods[] = { - { "SurfaceTextureBridge", - gfx::SurfaceTextureBridge::RegisterSurfaceTextureBridge }, - { "SurfaceTextureListener", - gfx::SurfaceTextureListener::RegisterSurfaceTextureListener }, -}; - -bool RegisterJni(JNIEnv* env) { - return RegisterNativeMethods(env, kGLRegisteredMethods, - arraysize(kGLRegisteredMethods)); -} - -} // namespace android -} // namespace gl -} // namespace ui diff --git a/chromium/ui/gl/android/gl_jni_registrar.h b/chromium/ui/gl/android/gl_jni_registrar.h deleted file mode 100644 index 468557c3e79..00000000000 --- a/chromium/ui/gl/android/gl_jni_registrar.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 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. - -#ifndef UI_GL_ANDROID_UI_JNI_REGISTRAR_H_ -#define UI_GL_ANDROID_UI_JNI_REGISTRAR_H_ - -#include <jni.h> - -#include "ui/gl/gl_export.h" - -namespace ui { -namespace gl { -namespace android { - -// Register all JNI bindings necessary for chrome. -GL_EXPORT bool RegisterJni(JNIEnv* env); - -} // namespace android -} // namespace gl -} // namespace ui - -#endif // UI_GL_ANDROID_UI_JNI_REGISTRAR_H_ diff --git a/chromium/ui/gl/android/scoped_java_surface.cc b/chromium/ui/gl/android/scoped_java_surface.cc index fe6a75e9ace..36f635fe01a 100644 --- a/chromium/ui/gl/android/scoped_java_surface.cc +++ b/chromium/ui/gl/android/scoped_java_surface.cc @@ -6,7 +6,7 @@ #include "base/logging.h" #include "jni/Surface_jni.h" -#include "ui/gl/android/surface_texture_bridge.h" +#include "ui/gl/android/surface_texture.h" namespace { @@ -37,7 +37,7 @@ ScopedJavaSurface::ScopedJavaSurface( } ScopedJavaSurface::ScopedJavaSurface( - const SurfaceTextureBridge* surface_texture) + const SurfaceTexture* surface_texture) : auto_release_(true), is_protected_(false) { JNIEnv* env = base::android::AttachCurrentThread(); diff --git a/chromium/ui/gl/android/scoped_java_surface.h b/chromium/ui/gl/android/scoped_java_surface.h index b50485b876f..54ed2a45190 100644 --- a/chromium/ui/gl/android/scoped_java_surface.h +++ b/chromium/ui/gl/android/scoped_java_surface.h @@ -13,7 +13,7 @@ namespace gfx { -class SurfaceTextureBridge; +class SurfaceTexture; // A helper class for holding a scoped reference to a Java Surface instance. // When going out of scope, Surface.release() is called on the Java object to @@ -29,7 +29,7 @@ class GL_EXPORT ScopedJavaSurface { // Creates a Java Surface from a SurfaceTexture and wraps it in a // ScopedJavaSurface. - explicit ScopedJavaSurface(const SurfaceTextureBridge* surface_texture); + explicit ScopedJavaSurface(const SurfaceTexture* surface_texture); // Move constructor. Take the surface from another ScopedJavaSurface object, // the latter no longer owns the surface afterwards. diff --git a/chromium/ui/gl/android/surface_texture_bridge.cc b/chromium/ui/gl/android/surface_texture.cc index 9f2a3372e84..d900972c9d1 100644 --- a/chromium/ui/gl/android/surface_texture_bridge.cc +++ b/chromium/ui/gl/android/surface_texture.cc @@ -1,8 +1,8 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// 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 "ui/gl/android/surface_texture_bridge.h" +#include "ui/gl/android/surface_texture.h" #include <android/native_window_jni.h> @@ -10,7 +10,7 @@ #include "base/android/build_info.h" #include "base/android/jni_android.h" #include "base/logging.h" -#include "jni/SurfaceTextureBridge_jni.h" +#include "jni/SurfaceTexturePlatformWrapper_jni.h" #include "ui/gl/android/scoped_java_surface.h" #include "ui/gl/android/surface_texture_listener.h" #include "ui/gl/gl_bindings.h" @@ -26,36 +26,38 @@ bool GlContextMethodsAvailable() { namespace gfx { -SurfaceTextureBridge::SurfaceTextureBridge(int texture_id) { +SurfaceTexture::SurfaceTexture(int texture_id) { JNIEnv* env = base::android::AttachCurrentThread(); - j_surface_texture_.Reset(Java_SurfaceTextureBridge_create(env, texture_id)); + j_surface_texture_.Reset( + Java_SurfaceTexturePlatformWrapper_create(env, texture_id)); } -SurfaceTextureBridge::~SurfaceTextureBridge() { +SurfaceTexture::~SurfaceTexture() { JNIEnv* env = base::android::AttachCurrentThread(); - Java_SurfaceTextureBridge_destroy(env, j_surface_texture_.obj()); + Java_SurfaceTexturePlatformWrapper_destroy(env, j_surface_texture_.obj()); } -void SurfaceTextureBridge::SetFrameAvailableCallback( +void SurfaceTexture::SetFrameAvailableCallback( const base::Closure& callback) { JNIEnv* env = base::android::AttachCurrentThread(); - Java_SurfaceTextureBridge_setFrameAvailableCallback( + Java_SurfaceTexturePlatformWrapper_setFrameAvailableCallback( env, j_surface_texture_.obj(), reinterpret_cast<int>(new SurfaceTextureListener(callback))); } -void SurfaceTextureBridge::UpdateTexImage() { +void SurfaceTexture::UpdateTexImage() { JNIEnv* env = base::android::AttachCurrentThread(); - Java_SurfaceTextureBridge_updateTexImage(env, j_surface_texture_.obj()); + Java_SurfaceTexturePlatformWrapper_updateTexImage(env, + j_surface_texture_.obj()); } -void SurfaceTextureBridge::GetTransformMatrix(float mtx[16]) { +void SurfaceTexture::GetTransformMatrix(float mtx[16]) { JNIEnv* env = base::android::AttachCurrentThread(); base::android::ScopedJavaLocalRef<jfloatArray> jmatrix( env, env->NewFloatArray(16)); - Java_SurfaceTextureBridge_getTransformMatrix( + Java_SurfaceTexturePlatformWrapper_getTransformMatrix( env, j_surface_texture_.obj(), jmatrix.obj()); jboolean is_copy; @@ -66,11 +68,11 @@ void SurfaceTextureBridge::GetTransformMatrix(float mtx[16]) { env->ReleaseFloatArrayElements(jmatrix.obj(), elements, JNI_ABORT); } -void SurfaceTextureBridge::SetDefaultBufferSize(int width, int height) { +void SurfaceTexture::SetDefaultBufferSize(int width, int height) { JNIEnv* env = base::android::AttachCurrentThread(); if (width > 0 && height > 0) { - Java_SurfaceTextureBridge_setDefaultBufferSize( + Java_SurfaceTexturePlatformWrapper_setDefaultBufferSize( env, j_surface_texture_.obj(), static_cast<jint>(width), static_cast<jint>(height)); } else { @@ -79,26 +81,26 @@ void SurfaceTextureBridge::SetDefaultBufferSize(int width, int height) { } } -void SurfaceTextureBridge::AttachToGLContext() { +void SurfaceTexture::AttachToGLContext() { if (GlContextMethodsAvailable()) { int texture_id; glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texture_id); DCHECK(texture_id); JNIEnv* env = base::android::AttachCurrentThread(); - Java_SurfaceTextureBridge_attachToGLContext( + Java_SurfaceTexturePlatformWrapper_attachToGLContext( env, j_surface_texture_.obj(), texture_id); } } -void SurfaceTextureBridge::DetachFromGLContext() { +void SurfaceTexture::DetachFromGLContext() { if (GlContextMethodsAvailable()) { JNIEnv* env = base::android::AttachCurrentThread(); - Java_SurfaceTextureBridge_detachFromGLContext( + Java_SurfaceTexturePlatformWrapper_detachFromGLContext( env, j_surface_texture_.obj()); } } -ANativeWindow* SurfaceTextureBridge::CreateSurface() { +ANativeWindow* SurfaceTexture::CreateSurface() { JNIEnv* env = base::android::AttachCurrentThread(); ScopedJavaSurface surface(this); ANativeWindow* native_window = ANativeWindow_fromSurface( @@ -107,7 +109,7 @@ ANativeWindow* SurfaceTextureBridge::CreateSurface() { } // static -bool SurfaceTextureBridge::RegisterSurfaceTextureBridge(JNIEnv* env) { +bool SurfaceTexture::RegisterSurfaceTexture(JNIEnv* env) { return RegisterNativesImpl(env); } diff --git a/chromium/ui/gl/android/surface_texture_bridge.h b/chromium/ui/gl/android/surface_texture.h index 474f0c22d39..62e375f796f 100644 --- a/chromium/ui/gl/android/surface_texture_bridge.h +++ b/chromium/ui/gl/android/surface_texture.h @@ -1,9 +1,9 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// 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. -#ifndef UI_GL_ANDROID_SURFACE_TEXTURE_BRIDGE_H_ -#define UI_GL_ANDROID_SURFACE_TEXTURE_BRIDGE_H_ +#ifndef UI_GL_ANDROID_SURFACE_TEXTURE_H_ +#define UI_GL_ANDROID_SURFACE_TEXTURE_H_ #include <jni.h> @@ -18,10 +18,10 @@ namespace gfx { // This class serves as a bridge for native code to call java functions inside // android SurfaceTexture class. -class GL_EXPORT SurfaceTextureBridge - : public base::RefCountedThreadSafe<SurfaceTextureBridge>{ +class GL_EXPORT SurfaceTexture + : public base::RefCountedThreadSafe<SurfaceTexture>{ public: - explicit SurfaceTextureBridge(int texture_id); + explicit SurfaceTexture(int texture_id); // Set the listener callback, which will be invoked on the same thread that // is being called from here for registration. @@ -57,18 +57,18 @@ class GL_EXPORT SurfaceTextureBridge return j_surface_texture_; } - static bool RegisterSurfaceTextureBridge(JNIEnv* env); + static bool RegisterSurfaceTexture(JNIEnv* env); private: - friend class base::RefCountedThreadSafe<SurfaceTextureBridge>; - ~SurfaceTextureBridge(); + friend class base::RefCountedThreadSafe<SurfaceTexture>; + ~SurfaceTexture(); // Java SurfaceTexture instance. base::android::ScopedJavaGlobalRef<jobject> j_surface_texture_; - DISALLOW_COPY_AND_ASSIGN(SurfaceTextureBridge); + DISALLOW_COPY_AND_ASSIGN(SurfaceTexture); }; } // namespace gfx -#endif // UI_GL_ANDROID_SURFACE_TEXTURE_BRIDGE_H_ +#endif // UI_GL_ANDROID_SURFACE_TEXTURE_H_ diff --git a/chromium/ui/gl/android/surface_texture_listener.cc b/chromium/ui/gl/android/surface_texture_listener.cc index 39d8468dd4a..8e2f89c5256 100644 --- a/chromium/ui/gl/android/surface_texture_listener.cc +++ b/chromium/ui/gl/android/surface_texture_listener.cc @@ -8,7 +8,7 @@ #include "base/logging.h" #include "base/message_loop/message_loop_proxy.h" #include "jni/SurfaceTextureListener_jni.h" -#include "ui/gl/android/surface_texture_bridge.h" +#include "ui/gl/android/surface_texture.h" namespace gfx { diff --git a/chromium/ui/gl/android/surface_texture_listener.h b/chromium/ui/gl/android/surface_texture_listener.h index 60103aad97d..823bc300642 100644 --- a/chromium/ui/gl/android/surface_texture_listener.h +++ b/chromium/ui/gl/android/surface_texture_listener.h @@ -33,7 +33,7 @@ class GL_EXPORT SurfaceTextureListener { SurfaceTextureListener(const base::Closure& callback); ~SurfaceTextureListener(); - friend class SurfaceTextureBridge; + friend class SurfaceTexture; base::Closure callback_; diff --git a/chromium/ui/gl/generate_bindings.py b/chromium/ui/gl/generate_bindings.py index 3b37a1708c5..a3f64ae24cf 100755 --- a/chromium/ui/gl/generate_bindings.py +++ b/chromium/ui/gl/generate_bindings.py @@ -432,6 +432,13 @@ GL_FUNCTIONS = [ { 'return_type': 'void*', 'names': ['glMapBuffer', 'glMapBufferOES'], 'arguments': 'GLenum target, GLenum access', }, +{ 'return_type': 'void*', + 'names': ['glMapBufferRange'], + 'arguments': + 'GLenum target, GLintptr offset, GLsizeiptr length, GLenum access', }, +{ 'return_type': 'void', + 'names': ['glFlushMappedBufferRange'], + 'arguments': 'GLenum target, GLintptr offset, GLsizeiptr length', }, { 'return_type': 'void', 'names': ['glPixelStorei'], 'arguments': 'GLenum pname, GLint param', }, @@ -740,7 +747,7 @@ GL_FUNCTIONS = [ 'APPLE_vertex_array_object', 'ARB_vertex_array_object'] }, { 'return_type': 'void', - 'names': ['glDiscardFramebufferEXT'], + 'names': ['glDiscardFramebufferEXT', 'glInvalidateFramebuffer'], 'arguments': 'GLenum target, GLsizei numAttachments, ' 'const GLenum* attachments' }, ] @@ -945,6 +952,10 @@ EGL_FUNCTIONS = [ 'EGLDisplay dpy, EGLSurface surface, ' 'EGLuint64CHROMIUM* ust, EGLuint64CHROMIUM* msc, ' 'EGLuint64CHROMIUM* sbc', }, +{ 'return_type': 'EGLint', + 'names': ['eglWaitSyncKHR'], + 'arguments': 'EGLDisplay dpy, EGLSyncKHR sync, EGLint flags', + 'other_extensions': ['EGL_KHR_wait_sync'] }, ] WGL_FUNCTIONS = [ diff --git a/chromium/ui/gl/gl.gyp b/chromium/ui/gl/gl.gyp index 139a88f2626..274065bd8d4 100644 --- a/chromium/ui/gl/gl.gyp +++ b/chromium/ui/gl/gl.gyp @@ -44,8 +44,8 @@ 'android/gl_jni_registrar.h', 'android/scoped_java_surface.cc', 'android/scoped_java_surface.h', - 'android/surface_texture_bridge.cc', - 'android/surface_texture_bridge.h', + 'android/surface_texture.cc', + 'android/surface_texture.h', 'android/surface_texture_listener.cc', 'android/surface_texture_listener.h', 'gl_bindings.h', @@ -133,7 +133,8 @@ 'action_name': 'generate_gl_bindings', 'variables': { 'generator_path': 'generate_bindings.py', - 'header_paths': '../../third_party/mesa/src/include:../../third_party/khronos', + # Prefer khronos EGL/GLES headers by listing that path first. + 'header_paths': '../../third_party/khronos:../../third_party/mesa/src/include', }, 'inputs': [ '<(generator_path)', @@ -328,7 +329,7 @@ 'surface_jni_headers', ], 'sources': [ - '../android/java/src/org/chromium/ui/gfx/SurfaceTextureBridge.java', + '../android/java/src/org/chromium/ui/gfx/SurfaceTexturePlatformWrapper.java', '../android/java/src/org/chromium/ui/gfx/SurfaceTextureListener.java', ], 'variables': { diff --git a/chromium/ui/gl/gl_bindings.h b/chromium/ui/gl/gl_bindings.h index 987ec203474..debb0748046 100644 --- a/chromium/ui/gl/gl_bindings.h +++ b/chromium/ui/gl/gl_bindings.h @@ -124,8 +124,8 @@ #define GL_LATENCY_QUERY_CHROMIUM 0x84F4 /* GL_CHROMIUM_async_pixel_transfers */ -#define GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM 0x84F5 -#define GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM 0x84F6 +#define GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM 0x84F5 +#define GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM 0x84F6 // GL_OES_texure_3D #define GL_SAMPLER_3D_OES 0x8B5F diff --git a/chromium/ui/gl/gl_context_android.cc b/chromium/ui/gl/gl_context_android.cc index d8238db54b6..a9e888b203d 100644 --- a/chromium/ui/gl/gl_context_android.cc +++ b/chromium/ui/gl/gl_context_android.cc @@ -20,15 +20,14 @@ namespace { // Used to render into an already current context+surface, // that we do not have ownership of (draw callback). +// TODO(boliu): Make this inherit from GLContextEGL. class GLNonOwnedContext : public GLContextReal { public: GLNonOwnedContext(GLShareGroup* share_group); // Implement GLContext. virtual bool Initialize(GLSurface* compatible_surface, - GpuPreference gpu_preference) OVERRIDE { - return true; - } + GpuPreference gpu_preference) OVERRIDE; virtual void Destroy() OVERRIDE {} virtual bool MakeCurrent(GLSurface* surface) OVERRIDE; virtual void ReleaseCurrent(GLSurface* surface) OVERRIDE {} @@ -42,10 +41,18 @@ class GLNonOwnedContext : public GLContextReal { private: DISALLOW_COPY_AND_ASSIGN(GLNonOwnedContext); + + EGLDisplay display_; }; GLNonOwnedContext::GLNonOwnedContext(GLShareGroup* share_group) - : GLContextReal(share_group) {} + : GLContextReal(share_group), display_(NULL) {} + +bool GLNonOwnedContext::Initialize(GLSurface* compatible_surface, + GpuPreference gpu_preference) { + display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY); + return true; +} bool GLNonOwnedContext::MakeCurrent(GLSurface* surface) { SetCurrent(surface); @@ -54,7 +61,11 @@ bool GLNonOwnedContext::MakeCurrent(GLSurface* surface) { } std::string GLNonOwnedContext::GetExtensions() { - return GLContext::GetExtensions(); + const char* extensions = eglQueryString(display_, EGL_EXTENSIONS); + if (!extensions) + return GLContext::GetExtensions(); + + return GLContext::GetExtensions() + " " + extensions; } } // anonymous namespace @@ -101,7 +112,7 @@ bool GLContextEGL::GetTotalGpuMemory(size_t* bytes) { // Droid Razr M(1GB) 91MB // Galaxy Nexus(1GB) 85MB // Xoom(1GB) 85MB - // Nexus S(low-end) 16MB + // Nexus S(low-end) 8MB static size_t limit_bytes = 0; if (limit_bytes == 0) { if (!base::android::SysUtils::IsLowEndDevice()) { @@ -114,7 +125,10 @@ bool GLContextEGL::GetTotalGpuMemory(size_t* bytes) { else limit_bytes = physical_memory_mb / 16; } else { - limit_bytes = physical_memory_mb / 32; + // Low-end devices have 512MB or less memory by definition + // so we hard code the limit rather than relying on the heuristics + // above. Low-end devices use 4444 textures so we can use a lower limit. + limit_bytes = 8; } limit_bytes = limit_bytes * 1024 * 1024; } diff --git a/chromium/ui/gl/gl_fence.cc b/chromium/ui/gl/gl_fence.cc index b9d9513f926..9b85300fabd 100644 --- a/chromium/ui/gl/gl_fence.cc +++ b/chromium/ui/gl/gl_fence.cc @@ -80,6 +80,7 @@ class EGLFenceSync : public gfx::GLFence { EGLFenceSync() { display_ = eglGetCurrentDisplay(); sync_ = eglCreateSyncKHR(display_, EGL_SYNC_FENCE_KHR, NULL); + glFlush(); } virtual bool HasCompleted() OVERRIDE { @@ -90,7 +91,7 @@ class EGLFenceSync : public gfx::GLFence { } virtual void ClientWait() OVERRIDE { - EGLint flags = EGL_SYNC_FLUSH_COMMANDS_BIT_KHR; + EGLint flags = 0; EGLTimeKHR time = EGL_FOREVER_KHR; eglClientWaitSyncKHR(display_, sync_, flags, time); } diff --git a/chromium/ui/gl/gl_image.h b/chromium/ui/gl/gl_image.h index f1d05371f6b..8d59bc46594 100644 --- a/chromium/ui/gl/gl_image.h +++ b/chromium/ui/gl/gl_image.h @@ -38,7 +38,9 @@ class GL_EXPORT GLImage : public base::RefCounted<GLImage> { // Create a GL image for a GPU Memory buffer. static scoped_refptr<GLImage> CreateGLImageForGpuMemoryBuffer( - gfx::GpuMemoryBufferHandle buffer, gfx::Size size); + gfx::GpuMemoryBufferHandle buffer, + gfx::Size size, + unsigned internalformat); protected: virtual ~GLImage(); diff --git a/chromium/ui/gl/gl_image_android.cc b/chromium/ui/gl/gl_image_android.cc index fe871e7b5e3..e56dc2d074b 100644 --- a/chromium/ui/gl/gl_image_android.cc +++ b/chromium/ui/gl/gl_image_android.cc @@ -26,13 +26,16 @@ scoped_refptr<GLImage> GLImage::CreateGLImage(gfx::PluginWindowHandle window) { } scoped_refptr<GLImage> GLImage::CreateGLImageForGpuMemoryBuffer( - gfx::GpuMemoryBufferHandle buffer, gfx::Size size) { + gfx::GpuMemoryBufferHandle buffer, + gfx::Size size, + unsigned internalformat) { TRACE_EVENT0("gpu", "GLImage::CreateGLImageForGpuMemoryBuffer"); switch (GetGLImplementation()) { case kGLImplementationEGLGLES2: switch (buffer.type) { case SHARED_MEMORY_BUFFER: { - scoped_refptr<GLImageShm> image(new GLImageShm(size)); + scoped_refptr<GLImageShm> image( + new GLImageShm(size, internalformat)); if (!image->Initialize(buffer)) return NULL; diff --git a/chromium/ui/gl/gl_image_mac.cc b/chromium/ui/gl/gl_image_mac.cc index b244a22ad93..04dc61e870b 100644 --- a/chromium/ui/gl/gl_image_mac.cc +++ b/chromium/ui/gl/gl_image_mac.cc @@ -27,7 +27,9 @@ scoped_refptr<GLImage> GLImage::CreateGLImage(gfx::PluginWindowHandle window) { } scoped_refptr<GLImage> GLImage::CreateGLImageForGpuMemoryBuffer( - gfx::GpuMemoryBufferHandle buffer, gfx::Size size) { + gfx::GpuMemoryBufferHandle buffer, + gfx::Size size, + unsigned internalformat) { TRACE_EVENT0("gpu", "GLImage::CreateGLImageForGpuMemoryBuffer"); switch (GetGLImplementation()) { case kGLImplementationOSMesaGL: @@ -35,7 +37,8 @@ scoped_refptr<GLImage> GLImage::CreateGLImageForGpuMemoryBuffer( case kGLImplementationAppleGL: switch (buffer.type) { case SHARED_MEMORY_BUFFER: { - scoped_refptr<GLImageShm> image(new GLImageShm(size)); + scoped_refptr<GLImageShm> image( + new GLImageShm(size, internalformat)); if (!image->Initialize(buffer)) return NULL; diff --git a/chromium/ui/gl/gl_image_ozone.cc b/chromium/ui/gl/gl_image_ozone.cc index c217f9992c8..a1c13296aae 100644 --- a/chromium/ui/gl/gl_image_ozone.cc +++ b/chromium/ui/gl/gl_image_ozone.cc @@ -27,7 +27,9 @@ scoped_refptr<GLImage> GLImage::CreateGLImage(gfx::PluginWindowHandle window) { } scoped_refptr<GLImage> GLImage::CreateGLImageForGpuMemoryBuffer( - gfx::GpuMemoryBufferHandle buffer, gfx::Size size) { + gfx::GpuMemoryBufferHandle buffer, + gfx::Size size, + unsigned internalformat) { TRACE_EVENT0("gpu", "GLImage::CreateGLImageForGpuMemoryBuffer"); switch (GetGLImplementation()) { case kGLImplementationOSMesaGL: diff --git a/chromium/ui/gl/gl_image_shm.cc b/chromium/ui/gl/gl_image_shm.cc index 14ed8364721..78e816496fb 100644 --- a/chromium/ui/gl/gl_image_shm.cc +++ b/chromium/ui/gl/gl_image_shm.cc @@ -10,7 +10,11 @@ namespace gfx { -GLImageShm::GLImageShm(gfx::Size size) : size_(size) { +GLImageShm::GLImageShm(gfx::Size size, unsigned internalformat) + : size_(size), + internalformat_(internalformat) { + // GL_RGBA8_OES is currently the only supported internalformat. + DCHECK_EQ(static_cast<GLenum>(GL_RGBA8_OES), internalformat); } GLImageShm::~GLImageShm() { @@ -40,8 +44,23 @@ bool GLImageShm::BindTexImage() { TRACE_EVENT0("gpu", "GLImageShm::BindTexImage"); DCHECK(shared_memory_); - const int kBytesPerPixel = 4; - size_t size = size_.GetArea() * kBytesPerPixel; + GLenum internalformat; + GLenum format; + GLenum type; + int bytes_per_pixel; + switch (internalformat_) { + case GL_RGBA8_OES: + internalformat = GL_RGBA; + format = GL_RGBA; + type = GL_UNSIGNED_BYTE; + bytes_per_pixel = 4; + break; + default: + DVLOG(0) << "Invalid format: " << internalformat_; + return false; + } + + size_t size = size_.GetArea() * bytes_per_pixel; DCHECK(!shared_memory_->memory()); if (!shared_memory_->Map(size)) { DVLOG(0) << "Failed to map shared memory."; @@ -51,12 +70,12 @@ bool GLImageShm::BindTexImage() { DCHECK(shared_memory_->memory()); glTexImage2D(GL_TEXTURE_2D, 0, // mip level - GL_RGBA, + internalformat, size_.width(), size_.height(), 0, // border - GL_RGBA, - GL_UNSIGNED_BYTE, + format, + type, shared_memory_->memory()); shared_memory_->Unmap(); diff --git a/chromium/ui/gl/gl_image_shm.h b/chromium/ui/gl/gl_image_shm.h index 70233f9a3be..ffdfc8b98da 100644 --- a/chromium/ui/gl/gl_image_shm.h +++ b/chromium/ui/gl/gl_image_shm.h @@ -12,7 +12,7 @@ namespace gfx { class GL_EXPORT GLImageShm : public GLImage { public: - explicit GLImageShm(gfx::Size size); + GLImageShm(gfx::Size size, unsigned internalformat); bool Initialize(gfx::GpuMemoryBufferHandle buffer); @@ -28,6 +28,7 @@ class GL_EXPORT GLImageShm : public GLImage { private: scoped_ptr<base::SharedMemory> shared_memory_; gfx::Size size_; + unsigned internalformat_; DISALLOW_COPY_AND_ASSIGN(GLImageShm); }; diff --git a/chromium/ui/gl/gl_image_win.cc b/chromium/ui/gl/gl_image_win.cc index 26b4a8f6920..1486520d6a7 100644 --- a/chromium/ui/gl/gl_image_win.cc +++ b/chromium/ui/gl/gl_image_win.cc @@ -27,7 +27,9 @@ scoped_refptr<GLImage> GLImage::CreateGLImage(gfx::PluginWindowHandle window) { } scoped_refptr<GLImage> GLImage::CreateGLImageForGpuMemoryBuffer( - gfx::GpuMemoryBufferHandle buffer, gfx::Size size) { + gfx::GpuMemoryBufferHandle buffer, + gfx::Size size, + unsigned internalformat) { TRACE_EVENT0("gpu", "GLImage::CreateGLImageForGpuMemoryBuffer"); switch (GetGLImplementation()) { case kGLImplementationOSMesaGL: @@ -35,7 +37,8 @@ scoped_refptr<GLImage> GLImage::CreateGLImageForGpuMemoryBuffer( case kGLImplementationEGLGLES2: switch (buffer.type) { case SHARED_MEMORY_BUFFER: { - scoped_refptr<GLImageShm> image(new GLImageShm(size)); + scoped_refptr<GLImageShm> image( + new GLImageShm(size, internalformat)); if (!image->Initialize(buffer)) return NULL; diff --git a/chromium/ui/gl/gl_image_x11.cc b/chromium/ui/gl/gl_image_x11.cc index a6c09a15137..6f7d8c6e85b 100644 --- a/chromium/ui/gl/gl_image_x11.cc +++ b/chromium/ui/gl/gl_image_x11.cc @@ -35,7 +35,9 @@ scoped_refptr<GLImage> GLImage::CreateGLImage(gfx::PluginWindowHandle window) { } scoped_refptr<GLImage> GLImage::CreateGLImageForGpuMemoryBuffer( - gfx::GpuMemoryBufferHandle buffer, gfx::Size size) { + gfx::GpuMemoryBufferHandle buffer, + gfx::Size size, + unsigned internalformat) { TRACE_EVENT0("gpu", "GLImage::CreateGLImageForGpuMemoryBuffer"); switch (GetGLImplementation()) { case kGLImplementationOSMesaGL: @@ -43,7 +45,8 @@ scoped_refptr<GLImage> GLImage::CreateGLImageForGpuMemoryBuffer( case kGLImplementationEGLGLES2: switch (buffer.type) { case SHARED_MEMORY_BUFFER: { - scoped_refptr<GLImageShm> image(new GLImageShm(size)); + scoped_refptr<GLImageShm> image( + new GLImageShm(size, internalformat)); if (!image->Initialize(buffer)) return NULL; diff --git a/chromium/ui/gl/gl_implementation_ozone.cc b/chromium/ui/gl/gl_implementation_ozone.cc index 607078a4797..d4e3dda9bcc 100644 --- a/chromium/ui/gl/gl_implementation_ozone.cc +++ b/chromium/ui/gl/gl_implementation_ozone.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/ozone/surface_factory_ozone.h" +#include "ui/gfx/ozone/surface_factory_ozone.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_egl_api_implementation.h" #include "ui/gl/gl_gl_api_implementation.h" @@ -41,7 +41,7 @@ bool InitializeGLBindings(GLImplementation implementation) { case kGLImplementationOSMesaGL: return InitializeGLBindingsOSMesaGL(); case kGLImplementationEGLGLES2: - if (!ui::SurfaceFactoryOzone::GetInstance()->LoadEGLGLES2Bindings()) + if (!gfx::SurfaceFactoryOzone::GetInstance()->LoadEGLGLES2Bindings()) return false; SetGLImplementation(kGLImplementationEGLGLES2); InitializeGLBindingsGL(); diff --git a/chromium/ui/gl/gl_implementation_win.cc b/chromium/ui/gl/gl_implementation_win.cc index c98c3c01314..87328a306f8 100644 --- a/chromium/ui/gl/gl_implementation_win.cc +++ b/chromium/ui/gl/gl_implementation_win.cc @@ -8,6 +8,7 @@ #include "base/base_paths.h" #include "base/bind.h" #include "base/command_line.h" +#include "base/debug/trace_event.h" #include "base/files/file_path.h" #include "base/logging.h" #include "base/native_library.h" @@ -58,6 +59,45 @@ bool LoadD3DXLibrary(const base::FilePath& module_path, return true; } +const unsigned char* AngleGetTraceCategoryEnabledFlag(const char* name) { + return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(name); +} + +void AngleAddTraceEvent(char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + int num_args, + const char** arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + unsigned char flags) { + TRACE_EVENT_API_ADD_TRACE_EVENT(phase, + category_group_enabled, + name, + id, + num_args, + arg_names, + arg_types, + arg_values, + NULL, + flags); +} + +typedef const unsigned char* (*GetCategoryEnabledFlagFunc)(const char* name); +typedef void (*AddTraceEventFunc)(char phase, + const unsigned char* categoryGroupEnabled, + const char* name, + unsigned long long id, + int numArgs, + const char** argNames, + const unsigned char* argTypes, + const unsigned long long* argValues, + unsigned char flags); +typedef void (__stdcall *SetTraceFunctionPointersFunc)( + GetCategoryEnabledFlagFunc get_category_enabled_flag, + AddTraceEventFunc add_trace_event_func); + } // namespace void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) { @@ -167,6 +207,17 @@ bool InitializeGLBindings(GLImplementation implementation) { } #endif + if (!using_swift_shader) { + SetTraceFunctionPointersFunc set_trace_function_pointers = + reinterpret_cast<SetTraceFunctionPointersFunc>( + base::GetFunctionPointerFromNativeLibrary( + gles_library, "SetTraceFunctionPointers")); + if (set_trace_function_pointers) { + set_trace_function_pointers(&AngleGetTraceCategoryEnabledFlag, + &AngleAddTraceEvent); + } + } + GLGetProcAddressProc get_proc_address = reinterpret_cast<GLGetProcAddressProc>( base::GetFunctionPointerFromNativeLibrary( diff --git a/chromium/ui/gl/gl_surface_egl.cc b/chromium/ui/gl/gl_surface_egl.cc index 8c29342ab40..d93a94560fd 100644 --- a/chromium/ui/gl/gl_surface_egl.cc +++ b/chromium/ui/gl/gl_surface_egl.cc @@ -32,7 +32,7 @@ extern "C" { #endif #if defined (USE_OZONE) -#include "ui/base/ozone/surface_factory_ozone.h" +#include "ui/gfx/ozone/surface_factory_ozone.h" #endif // From ANGLE's egl/eglext.h. @@ -100,17 +100,24 @@ bool GLSurfaceEGL::InitializeOneOff() { if (initialized) return true; -#if defined (USE_OZONE) - ui::SurfaceFactoryOzone::GetInstance()->InitializeHardware(); -#endif - #if defined(USE_X11) g_native_display = base::MessagePumpForUI::GetDefaultXDisplay(); #elif defined(OS_WIN) g_native_display = EGL_DEFAULT_DISPLAY; - if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableD3D11)) { + if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableD3D11) && + CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableD3D11)) { g_native_display = EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE; } +#elif defined(USE_OZONE) + gfx::SurfaceFactoryOzone* surface_factory = + gfx::SurfaceFactoryOzone::GetInstance(); + if (surface_factory->InitializeHardware() != + gfx::SurfaceFactoryOzone::INITIALIZED) { + LOG(ERROR) << "OZONE failed to initialize hardware"; + return false; + } + g_native_display = reinterpret_cast<EGLNativeDisplayType>( + surface_factory->GetNativeDisplay()); #else g_native_display = EGL_DEFAULT_DISPLAY; #endif @@ -638,10 +645,10 @@ GLSurface::CreateViewGLSurface(gfx::AcceleratedWidget window) { scoped_refptr<NativeViewGLSurfaceEGL> surface; VSyncProvider* sync_provider = NULL; #if defined(USE_OZONE) - window = ui::SurfaceFactoryOzone::GetInstance()->RealizeAcceleratedWidget( + window = gfx::SurfaceFactoryOzone::GetInstance()->RealizeAcceleratedWidget( window); sync_provider = - ui::SurfaceFactoryOzone::GetInstance()->GetVSyncProvider(window); + gfx::SurfaceFactoryOzone::GetInstance()->GetVSyncProvider(window); #endif surface = new NativeViewGLSurfaceEGL(window); if(surface->Initialize(sync_provider)) diff --git a/chromium/ui/gl/gl_surface_glx.cc b/chromium/ui/gl/gl_surface_glx.cc index 8b705dfbe93..10020d30d9d 100644 --- a/chromium/ui/gl/gl_surface_glx.cc +++ b/chromium/ui/gl/gl_surface_glx.cc @@ -10,6 +10,7 @@ extern "C" { #include "base/basictypes.h" #include "base/debug/trace_event.h" +#include "base/lazy_instance.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" @@ -39,7 +40,7 @@ class ScopedPtrXFree { } }; -Display* g_display; +Display* g_display = NULL; const char* g_glx_extensions = NULL; bool g_glx_context_create = false; bool g_glx_create_context_robustness_supported = false; @@ -299,6 +300,73 @@ SGIVideoSyncThread* SGIVideoSyncThread::g_video_sync_thread = NULL; // goes up (rather than on-demand when we start the thread). Display* SGIVideoSyncProviderThreadShim::display_ = NULL; +#if defined(TOOLKIT_GTK) +// A mechanism for forwarding XExpose events from one window to another. +// Because in the workaround for http://crbug.com/145600 the child window +// is placed on top of the parent window, only the child window will receive +// all expose events. These need to be forwared to the parent window to inform +// it that it should paint. +class XExposeEventForwarder : public base::MessagePumpObserver { + public: + XExposeEventForwarder() {} + virtual ~XExposeEventForwarder() { + DCHECK(child_to_parent_map_.empty()); + } + void AddParentChildPair(gfx::AcceleratedWidget parent_window, + gfx::AcceleratedWidget child_window) { + if (child_to_parent_map_.empty()) + base::MessagePumpX11::Current()->AddObserver(this); + + DCHECK(child_to_parent_map_.find(child_window) == + child_to_parent_map_.end()); + child_to_parent_map_.insert(std::make_pair( + child_window, parent_window)); + } + void RemoveParentChildPair(gfx::AcceleratedWidget parent_window, + gfx::AcceleratedWidget child_window) { + DCHECK(child_to_parent_map_.find(child_window) != + child_to_parent_map_.end()); + child_to_parent_map_.erase(child_window); + + if (child_to_parent_map_.empty()) + base::MessagePumpX11::Current()->RemoveObserver(this); + } + + private: + virtual base::EventStatus WillProcessEvent ( + const base::NativeEvent& xevent) OVERRIDE { + if (xevent->type != Expose) + return base::EVENT_CONTINUE; + + WindowMap::const_iterator found = child_to_parent_map_.find( + xevent->xexpose.window); + if (found == child_to_parent_map_.end()) + return base::EVENT_CONTINUE; + + gfx::AcceleratedWidget target_window = found->second; + XEvent forwarded_event = *xevent; + forwarded_event.xexpose.window = target_window; + XSendEvent(g_display, target_window, False, ExposureMask, + &forwarded_event); + return base::EVENT_CONTINUE; + } + virtual void DidProcessEvent(const base::NativeEvent& xevent) OVERRIDE { + } + + typedef std::map<gfx::AcceleratedWidget, gfx::AcceleratedWidget> WindowMap; + WindowMap child_to_parent_map_; + + DISALLOW_COPY_AND_ASSIGN(XExposeEventForwarder); +}; + +static base::LazyInstance<XExposeEventForwarder> g_xexpose_event_forwarder = + LAZY_INSTANCE_INITIALIZER; + +// Do not use this workaround when running in test harnesses that do not have +// a message loop or do not have a TYPE_GPU message loop. +bool g_create_child_windows = false; +#endif + } // namespace GLSurfaceGLX::GLSurfaceGLX() {} @@ -315,7 +383,21 @@ bool GLSurfaceGLX::InitializeOneOff() { // it's own thread. XInitThreads(); +#if defined(TOOLKIT_GTK) + // Be sure to use the X display handle and not the GTK display handle if this + // is the GPU process. + g_create_child_windows = + base::MessageLoop::current() && + base::MessageLoop::current()->type() == base::MessageLoop::TYPE_GPU; + + if (g_create_child_windows) + g_display = base::MessagePumpX11::GetDefaultXDisplay(); + else + g_display = base::MessagePumpForUI::GetDefaultXDisplay(); +#else g_display = base::MessagePumpForUI::GetDefaultXDisplay(); +#endif + if (!g_display) { LOG(ERROR) << "XOpenDisplay failed."; return false; @@ -388,31 +470,127 @@ void* GLSurfaceGLX::GetDisplay() { GLSurfaceGLX::~GLSurfaceGLX() {} +#if defined(TOOLKIT_GTK) +bool NativeViewGLSurfaceGLX::SetBackbufferAllocation(bool allocated) { + backbuffer_allocated_ = allocated; + AdjustBufferAllocation(); + return true; +} + +void NativeViewGLSurfaceGLX::SetFrontbufferAllocation(bool allocated) { + frontbuffer_allocated_ = allocated; + AdjustBufferAllocation(); +} + +void NativeViewGLSurfaceGLX::AdjustBufferAllocation() { + if (!g_create_child_windows) + return; + + if (frontbuffer_allocated_ || backbuffer_allocated_) + CreateChildWindow(); + else + DestroyChildWindow(); +} + +void NativeViewGLSurfaceGLX::CreateChildWindow() { + DCHECK(g_create_child_windows); + + if (child_window_) + return; + + XSetWindowAttributes set_window_attributes; + set_window_attributes.event_mask = ExposureMask; + child_window_ = XCreateWindow( + g_display, parent_window_, 0, 0, size_.width(), size_.height(), 0, + CopyFromParent, InputOutput, CopyFromParent, CWEventMask, + &set_window_attributes); + g_xexpose_event_forwarder.Pointer()->AddParentChildPair( + parent_window_, child_window_); + + XMapWindow(g_display, child_window_); + XFlush(g_display); +} + +void NativeViewGLSurfaceGLX::DestroyChildWindow() { + if (!child_window_) + return; + + g_xexpose_event_forwarder.Pointer()->RemoveParentChildPair( + parent_window_, child_window_); + XDestroyWindow(g_display, child_window_); + XFlush(g_display); + child_window_ = 0; +} +#endif + NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::AcceleratedWidget window) - : window_(window), + : parent_window_(window), +#if defined(TOOLKIT_GTK) + child_window_(0), + dummy_window_(0), + backbuffer_allocated_(true), + frontbuffer_allocated_(true), +#endif config_(NULL) { } +gfx::AcceleratedWidget NativeViewGLSurfaceGLX::GetDrawableHandle() const { +#if defined(TOOLKIT_GTK) + if (g_create_child_windows) { + if (child_window_) + return child_window_; + return dummy_window_; + } +#endif + return parent_window_; +} + bool NativeViewGLSurfaceGLX::Initialize() { XWindowAttributes attributes; - if (!XGetWindowAttributes(g_display, window_, &attributes)) { - LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << "."; + if (!XGetWindowAttributes(g_display, parent_window_, &attributes)) { + LOG(ERROR) << "XGetWindowAttributes failed for window " << parent_window_ + << "."; return false; } size_ = gfx::Size(attributes.width, attributes.height); + gfx::AcceleratedWidget window_for_vsync = parent_window_; + +#if defined(TOOLKIT_GTK) + if (g_create_child_windows) { + dummy_window_ = XCreateWindow( + g_display, + RootWindow(g_display, XScreenNumberOfScreen(attributes.screen)), + 0, 0, 1, 1, 0, CopyFromParent, InputOutput, attributes.visual, 0, NULL); + window_for_vsync = dummy_window_; + CreateChildWindow(); + } +#endif + if (g_glx_oml_sync_control_supported) - vsync_provider_.reset(new OMLSyncControlVSyncProvider(window_)); + vsync_provider_.reset(new OMLSyncControlVSyncProvider(window_for_vsync)); else if (g_glx_sgi_video_sync_supported) - vsync_provider_.reset(new SGIVideoSyncVSyncProvider(window_)); + vsync_provider_.reset(new SGIVideoSyncVSyncProvider(window_for_vsync)); return true; } void NativeViewGLSurfaceGLX::Destroy() { +#if defined(TOOLKIT_GTK) + DestroyChildWindow(); + if (dummy_window_) + XDestroyWindow(g_display, dummy_window_); + dummy_window_ = 0; +#endif } bool NativeViewGLSurfaceGLX::Resize(const gfx::Size& size) { +#if defined(TOOLKIT_GTK) + if (child_window_) { + XResizeWindow(g_display, child_window_, size.width(), size.height()); + XFlush(g_display); + } +#endif size_ = size; return true; } @@ -422,7 +600,7 @@ bool NativeViewGLSurfaceGLX::IsOffscreen() { } bool NativeViewGLSurfaceGLX::SwapBuffers() { - glXSwapBuffers(g_display, window_); + glXSwapBuffers(g_display, GetDrawableHandle()); return true; } @@ -431,7 +609,7 @@ gfx::Size NativeViewGLSurfaceGLX::GetSize() { } void* NativeViewGLSurfaceGLX::GetHandle() { - return reinterpret_cast<void*>(window_); + return reinterpret_cast<void*>(GetDrawableHandle()); } std::string NativeViewGLSurfaceGLX::GetExtensions() { @@ -460,10 +638,10 @@ void* NativeViewGLSurfaceGLX::GetConfig() { XWindowAttributes attributes; if (!XGetWindowAttributes( g_display, - window_, + parent_window_, &attributes)) { LOG(ERROR) << "XGetWindowAttributes failed for window " << - window_ << "."; + parent_window_ << "."; return NULL; } @@ -507,7 +685,7 @@ void* NativeViewGLSurfaceGLX::GetConfig() { bool NativeViewGLSurfaceGLX::PostSubBuffer( int x, int y, int width, int height) { DCHECK(gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer); - glXCopySubBufferMESA(g_display, window_, x, y, width, height); + glXCopySubBufferMESA(g_display, GetDrawableHandle(), x, y, width, height); return true; } @@ -516,7 +694,13 @@ VSyncProvider* NativeViewGLSurfaceGLX::GetVSyncProvider() { } NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX() - : window_(0), + : parent_window_(0), +#if defined(TOOLKIT_GTK) + child_window_(0), + dummy_window_(0), + backbuffer_allocated_(true), + frontbuffer_allocated_(true), +#endif config_(NULL) { } diff --git a/chromium/ui/gl/gl_surface_glx.h b/chromium/ui/gl/gl_surface_glx.h index 355b65d1c45..8e7bd1c0c78 100644 --- a/chromium/ui/gl/gl_surface_glx.h +++ b/chromium/ui/gl/gl_surface_glx.h @@ -69,9 +69,41 @@ class GL_EXPORT NativeViewGLSurfaceGLX : public GLSurfaceGLX { NativeViewGLSurfaceGLX(); virtual ~NativeViewGLSurfaceGLX(); - gfx::AcceleratedWidget window_; - private: + // The handle for the drawable to make current or swap. + gfx::AcceleratedWidget GetDrawableHandle() const; + + // Window passed in at creation. Always valid. + gfx::AcceleratedWidget parent_window_; + +#if defined(TOOLKIT_GTK) + // Some NVIDIA drivers don't allow deleting GLX windows separately from their + // parent X windows. Work around this by creating a child X window to the + // window passed in to the constructor, creating the GLX window against the + // child window, and then destroying the child window to destroy the GLX + // window. + // http://crbug.com/145600 + void CreateChildWindow(); + void DestroyChildWindow(); + + // Destroy the child window when both the front and back buffers are + // deallocated. + virtual bool SetBackbufferAllocation(bool allocated) OVERRIDE; + virtual void SetFrontbufferAllocation(bool allocated) OVERRIDE; + void AdjustBufferAllocation(); + + // Child window which is used with GLX, and is discarded when it is + // backgrounded. + gfx::AcceleratedWidget child_window_; + + // Dummy 1x1 window which is supplied to glXMakeCurrent when making + // the context current while its output surface is destroyed. + gfx::AcceleratedWidget dummy_window_; + + bool backbuffer_allocated_; + bool frontbuffer_allocated_; +#endif + void* config_; gfx::Size size_; diff --git a/chromium/ui/gl/gl_switches.cc b/chromium/ui/gl/gl_switches.cc index 2649abac806..6addfe126fc 100644 --- a/chromium/ui/gl/gl_switches.cc +++ b/chromium/ui/gl/gl_switches.cc @@ -18,6 +18,9 @@ const char kGLImplementationMockName[] = "mock"; namespace switches { +// Enables use of D3D11 when available. +const char kEnableD3D11[] = "enable-d3d11"; + // Disables use of D3D11. const char kDisableD3D11[] = "disable-d3d11"; @@ -70,6 +73,7 @@ const char kTestGLLib[] = "test-gl-lib"; // to read it in the GPU process, else don't add it. const char* kGLSwitchesCopiedFromGpuProcessHost[] = { kDisableGpuVsync, + kEnableD3D11, kDisableD3D11, kEnableGPUServiceLogging, kEnableGPUServiceTracing, diff --git a/chromium/ui/gl/gl_switches.h b/chromium/ui/gl/gl_switches.h index f776f5b4538..57590d7bd87 100644 --- a/chromium/ui/gl/gl_switches.h +++ b/chromium/ui/gl/gl_switches.h @@ -23,6 +23,7 @@ extern const char kGLImplementationMockName[]; namespace switches { +GL_EXPORT extern const char kEnableD3D11[]; GL_EXPORT extern const char kDisableD3D11[]; GL_EXPORT extern const char kDisableGpuVsync[]; GL_EXPORT extern const char kEnableGPUServiceLogging[]; diff --git a/chromium/ui/keyboard/keyboard.gyp b/chromium/ui/keyboard/keyboard.gyp index d4d7ea17298..7ec43f36edb 100644 --- a/chromium/ui/keyboard/keyboard.gyp +++ b/chromium/ui/keyboard/keyboard.gyp @@ -92,14 +92,13 @@ 'keyboard_test_suite.cc', ], 'conditions': [ - [ 'os_posix == 1 and OS != "mac" and OS != "android" and OS != "ios"', { - 'conditions': [ - ['linux_use_tcmalloc==1', { - 'dependencies': [ - '../../base/allocator/allocator.gyp:allocator', - ], - }], + ['OS=="linux" and linux_use_tcmalloc==1', { + 'dependencies': [ + '<(DEPTH)/base/allocator/allocator.gyp:allocator', ], + 'link_settings': { + 'ldflags': ['-rdynamic'], + }, }], ], }, diff --git a/chromium/ui/keyboard/keyboard_controller.cc b/chromium/ui/keyboard/keyboard_controller.cc index 1a3d88db3e1..83e7f321c5c 100644 --- a/chromium/ui/keyboard/keyboard_controller.cc +++ b/chromium/ui/keyboard/keyboard_controller.cc @@ -4,9 +4,11 @@ #include "ui/keyboard/keyboard_controller.h" +#include "base/bind.h" #include "ui/aura/layout_manager.h" #include "ui/aura/window.h" #include "ui/aura/window_delegate.h" +#include "ui/base/cursor/cursor.h" #include "ui/base/hit_test.h" #include "ui/base/ime/input_method.h" #include "ui/base/ime/text_input_client.h" @@ -19,6 +21,8 @@ namespace { +const int kHideKeyboardDelayMs = 100; + gfx::Rect KeyboardBoundsFromWindowBounds(const gfx::Rect& window_bounds) { const float kKeyboardHeightRatio = 0.3f; return gfx::Rect( @@ -68,7 +72,8 @@ class KeyboardWindowDelegate : public aura::WindowDelegate { gfx::Rect keyboard_bounds = KeyboardBoundsFromWindowBounds(bounds_); mask->addRect(RectToSkRect(keyboard_bounds)); } - virtual scoped_refptr<ui::Texture> CopyTexture() OVERRIDE { return NULL; } + virtual void DidRecreateLayer(ui::Layer* old_layer, + ui::Layer* new_layer) OVERRIDE {} gfx::Rect bounds_; DISALLOW_COPY_AND_ASSIGN(KeyboardWindowDelegate); @@ -118,7 +123,9 @@ class KeyboardLayoutManager : public aura::LayoutManager { KeyboardController::KeyboardController(KeyboardControllerProxy* proxy) : proxy_(proxy), container_(NULL), - input_method_(NULL) { + input_method_(NULL), + keyboard_visible_(false), + weak_factory_(this) { CHECK(proxy); input_method_ = proxy_->GetInputMethod(); input_method_->AddObserver(this); @@ -142,6 +149,16 @@ aura::Window* KeyboardController::GetContainerWindow() { return container_; } +void KeyboardController::HideKeyboard() { + keyboard_visible_ = false; + + FOR_EACH_OBSERVER(KeyboardControllerObserver, + observer_list_, + OnKeyboardBoundsChanging(gfx::Rect())); + + proxy_->HideKeyboardContainer(container_); +} + void KeyboardController::AddObserver(KeyboardControllerObserver* observer) { observer_list_.AddObserver(observer); } @@ -166,9 +183,11 @@ void KeyboardController::OnTextInputStateChanged( if (!container_) return; - bool was_showing = container_->IsVisible(); + bool was_showing = keyboard_visible_; bool should_show = was_showing; - if (!client || client->GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) { + ui::TextInputType type = + client ? client->GetTextInputType() : ui::TEXT_INPUT_TYPE_NONE; + if (type == ui::TEXT_INPUT_TYPE_NONE) { should_show = false; } else { if (container_->children().empty()) { @@ -177,25 +196,34 @@ void KeyboardController::OnTextInputStateChanged( container_->AddChild(keyboard); container_->layout_manager()->OnWindowResized(); } + proxy_->SetUpdateInputType(type); container_->parent()->StackChildAtTop(container_); should_show = true; } if (was_showing != should_show) { - gfx::Rect new_bounds( - should_show ? container_->children()[0]->bounds() : gfx::Rect()); - - FOR_EACH_OBSERVER( - KeyboardControllerObserver, - observer_list_, - OnKeyboardBoundsChanging(new_bounds)); - - if (should_show) + if (should_show) { + keyboard_visible_ = true; + weak_factory_.InvalidateWeakPtrs(); + if (container_->IsVisible()) + return; + + FOR_EACH_OBSERVER( + KeyboardControllerObserver, + observer_list_, + OnKeyboardBoundsChanging(container_->children()[0]->bounds())); proxy_->ShowKeyboardContainer(container_); - else - proxy_->HideKeyboardContainer(container_); + } else { + // Set the visibility state here so that any queries for visibility + // before the timer fires returns the correct future value. + keyboard_visible_ = false; + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&KeyboardController::HideKeyboard, + weak_factory_.GetWeakPtr()), + base::TimeDelta::FromMilliseconds(kHideKeyboardDelayMs)); + } } - // TODO(bryeung): whenever the TextInputClient changes we need to notify the // keyboard (with the TextInputType) so that it can reset it's state (e.g. // abandon compositions in progress) @@ -207,4 +235,8 @@ void KeyboardController::OnInputMethodDestroyed( input_method_ = NULL; } +bool KeyboardController::WillHideKeyboard() const { + return weak_factory_.HasWeakPtrs(); +} + } // namespace keyboard diff --git a/chromium/ui/keyboard/keyboard_controller.h b/chromium/ui/keyboard/keyboard_controller.h index 6022339c380..31f48d3da43 100644 --- a/chromium/ui/keyboard/keyboard_controller.h +++ b/chromium/ui/keyboard/keyboard_controller.h @@ -42,6 +42,11 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver, // It is the responsibility of the caller to Show() the returned window. aura::Window* GetContainerWindow(); + // Hides virtual keyboard and notifies observer bounds change. + // This function should be called with a delay to avoid layout flicker + // when the focus of input field quickly change. + void HideKeyboard(); + // Management of the observer list. virtual void AddObserver(KeyboardControllerObserver* observer); virtual void RemoveObserver(KeyboardControllerObserver* observer); @@ -61,9 +66,14 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver, virtual void OnInputMethodDestroyed( const ui::InputMethod* input_method) OVERRIDE; + // Returns true if keyboard is scheduled to hide. + bool WillHideKeyboard() const; + scoped_ptr<KeyboardControllerProxy> proxy_; aura::Window* container_; ui::InputMethod* input_method_; + bool keyboard_visible_; + base::WeakPtrFactory<KeyboardController> weak_factory_; ObserverList<KeyboardControllerObserver> observer_list_; diff --git a/chromium/ui/keyboard/keyboard_controller_proxy.cc b/chromium/ui/keyboard/keyboard_controller_proxy.cc index 6f73f276139..1cfb99d92b1 100644 --- a/chromium/ui/keyboard/keyboard_controller_proxy.cc +++ b/chromium/ui/keyboard/keyboard_controller_proxy.cc @@ -4,16 +4,53 @@ #include "ui/keyboard/keyboard_controller_proxy.h" +#include "base/values.h" #include "content/public/browser/site_instance.h" #include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_delegate.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_view.h" +#include "content/public/browser/web_ui.h" +#include "content/public/common/bindings_policy.h" #include "ui/aura/window.h" #include "ui/keyboard/keyboard_constants.h" namespace { +// Converts ui::TextInputType to string. +std::string TextInputTypeToString(ui::TextInputType type) { + switch (type) { + case ui::TEXT_INPUT_TYPE_NONE: + return "none"; + case ui::TEXT_INPUT_TYPE_PASSWORD: + return "password"; + case ui::TEXT_INPUT_TYPE_EMAIL: + return "email"; + case ui::TEXT_INPUT_TYPE_NUMBER: + return "number"; + case ui::TEXT_INPUT_TYPE_TELEPHONE: + return "tel"; + case ui::TEXT_INPUT_TYPE_URL: + return "url"; + case ui::TEXT_INPUT_TYPE_DATE: + return "date"; + case ui::TEXT_INPUT_TYPE_TEXT: + case ui::TEXT_INPUT_TYPE_SEARCH: + case ui::TEXT_INPUT_TYPE_DATE_TIME: + case ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL: + case ui::TEXT_INPUT_TYPE_MONTH: + case ui::TEXT_INPUT_TYPE_TIME: + case ui::TEXT_INPUT_TYPE_WEEK: + case ui::TEXT_INPUT_TYPE_TEXT_AREA: + case ui::TEXT_INPUT_TYPE_CONTENT_EDITABLE: + case ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD: + return "text"; + } + NOTREACHED(); + return ""; +} + // The WebContentsDelegate for the keyboard. // The delegate deletes itself when the keyboard is destroyed. class KeyboardContentsDelegate : public content::WebContentsDelegate, @@ -91,6 +128,20 @@ void KeyboardControllerProxy::HideKeyboardContainer(aura::Window* container) { container->Hide(); } +void KeyboardControllerProxy::SetUpdateInputType(ui::TextInputType type) { + content::WebUI* webui = keyboard_contents_ ? + keyboard_contents_->GetCommittedWebUI() : NULL; + + if (webui && + (0 != (webui->GetBindings() & content::BINDINGS_POLICY_WEB_UI))) { + // Only call OnTextInputBoxFocused function if it is a web ui keyboard, + // not an extension based keyboard. + base::DictionaryValue input_context; + input_context.SetString("type", TextInputTypeToString(type)); + webui->CallJavascriptFunction("OnTextInputBoxFocused", input_context); + } +} + void KeyboardControllerProxy::SetupWebContents(content::WebContents* contents) { } diff --git a/chromium/ui/keyboard/keyboard_controller_proxy.h b/chromium/ui/keyboard/keyboard_controller_proxy.h index e88e52b6005..53585977998 100644 --- a/chromium/ui/keyboard/keyboard_controller_proxy.h +++ b/chromium/ui/keyboard/keyboard_controller_proxy.h @@ -7,6 +7,7 @@ #include "base/memory/scoped_ptr.h" #include "content/public/common/media_stream_request.h" +#include "ui/base/ime/text_input_type.h" #include "ui/keyboard/keyboard_export.h" namespace aura { @@ -56,6 +57,11 @@ class KEYBOARD_EXPORT KeyboardControllerProxy { // necesasry animation, or delay the visibility change as it desires. virtual void HideKeyboardContainer(aura::Window* container); + // Updates the type of the focused text input box. The default implementation + // calls OnTextInputBoxFocused javascript function through webui to update the + // type the of focused input box. + virtual void SetUpdateInputType(ui::TextInputType type); + protected: // Gets the BrowserContext to use for creating the WebContents hosting the // keyboard. diff --git a/chromium/ui/keyboard/keyboard_controller_unittest.cc b/chromium/ui/keyboard/keyboard_controller_unittest.cc index 49c695a6177..1d461166ff6 100644 --- a/chromium/ui/keyboard/keyboard_controller_unittest.cc +++ b/chromium/ui/keyboard/keyboard_controller_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/bind.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "testing/gtest/include/gtest/gtest.h" @@ -134,16 +135,16 @@ class TestTextInputClient : public ui::TextInputClient { return false; } virtual bool HasCompositionText() OVERRIDE { return false; } - virtual bool GetTextRange(ui::Range* range) OVERRIDE { return false; } - virtual bool GetCompositionTextRange(ui::Range* range) OVERRIDE { + virtual bool GetTextRange(gfx::Range* range) OVERRIDE { return false; } + virtual bool GetCompositionTextRange(gfx::Range* range) OVERRIDE { return false; } - virtual bool GetSelectionRange(ui::Range* range) OVERRIDE { return false; } - virtual bool SetSelectionRange(const ui::Range& range) OVERRIDE { + virtual bool GetSelectionRange(gfx::Range* range) OVERRIDE { return false; } + virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE { return false; } - virtual bool DeleteRange(const ui::Range& range) OVERRIDE { return false; } - virtual bool GetTextFromRange(const ui::Range& range, + virtual bool DeleteRange(const gfx::Range& range) OVERRIDE { return false; } + virtual bool GetTextFromRange(const gfx::Range& range, base::string16* text) OVERRIDE { return false; } @@ -158,6 +159,27 @@ class TestTextInputClient : public ui::TextInputClient { DISALLOW_COPY_AND_ASSIGN(TestTextInputClient); }; +class KeyboardContainerObserver : public aura::WindowObserver { + public: + explicit KeyboardContainerObserver(aura::Window* window) : window_(window) { + window_->AddObserver(this); + } + virtual ~KeyboardContainerObserver() { + window_->RemoveObserver(this); + } + + private: + virtual void OnWindowVisibilityChanged(aura::Window* window, + bool visible) OVERRIDE { + if (!visible) + base::MessageLoop::current()->Quit(); + } + + aura::Window* window_; + + DISALLOW_COPY_AND_ASSIGN(KeyboardContainerObserver); +}; + } // namespace class KeyboardControllerTest : public testing::Test { @@ -170,6 +192,8 @@ class KeyboardControllerTest : public testing::Test { aura_test_helper_->SetUp(); ui::SetUpInputMethodFactoryForTesting(); focus_controller_.reset(new TestFocusController(root_window())); + proxy_ = new TestKeyboardControllerProxy(); + controller_.reset(new KeyboardController(proxy_)); } virtual void TearDown() OVERRIDE { @@ -178,37 +202,43 @@ class KeyboardControllerTest : public testing::Test { } aura::RootWindow* root_window() { return aura_test_helper_->root_window(); } + KeyboardControllerProxy* proxy() { return proxy_; } + KeyboardController* controller() { return controller_.get(); } - void ShowKeyboard(KeyboardController* controller) { + void ShowKeyboard() { TestTextInputClient test_text_input_client(ui::TEXT_INPUT_TYPE_TEXT); - controller->OnTextInputStateChanged(&test_text_input_client); + controller_->OnTextInputStateChanged(&test_text_input_client); } protected: + bool WillHideKeyboard() { + return controller_->WillHideKeyboard(); + } + base::MessageLoopForUI message_loop_; scoped_ptr<aura::test::AuraTestHelper> aura_test_helper_; scoped_ptr<TestFocusController> focus_controller_; private: + KeyboardControllerProxy* proxy_; + scoped_ptr<KeyboardController> controller_; + DISALLOW_COPY_AND_ASSIGN(KeyboardControllerTest); }; TEST_F(KeyboardControllerTest, KeyboardSize) { - KeyboardControllerProxy* proxy = new TestKeyboardControllerProxy(); - KeyboardController controller(proxy); - - scoped_ptr<aura::Window> container(controller.GetContainerWindow()); + scoped_ptr<aura::Window> container(controller()->GetContainerWindow()); gfx::Rect bounds(0, 0, 100, 100); container->SetBounds(bounds); - const gfx::Rect& before_bounds = proxy->GetKeyboardWindow()->bounds(); + const gfx::Rect& before_bounds = proxy()->GetKeyboardWindow()->bounds(); gfx::Rect new_bounds( before_bounds.x(), before_bounds.y(), before_bounds.width() / 2, before_bounds.height() / 2); // The KeyboardController's LayoutManager shouldn't let this happen - proxy->GetKeyboardWindow()->SetBounds(new_bounds); - ASSERT_EQ(before_bounds, proxy->GetKeyboardWindow()->bounds()); + proxy()->GetKeyboardWindow()->SetBounds(new_bounds); + ASSERT_EQ(before_bounds, proxy()->GetKeyboardWindow()->bounds()); } // Tests that tapping/clicking inside the keyboard does not give it focus. @@ -222,16 +252,14 @@ TEST_F(KeyboardControllerTest, ClickDoesNotFocusKeyboard) { window->Show(); window->Focus(); - KeyboardControllerProxy* proxy = new TestKeyboardControllerProxy(); - KeyboardController controller(proxy); - - scoped_ptr<aura::Window> keyboard_container(controller.GetContainerWindow()); + scoped_ptr<aura::Window> keyboard_container( + controller()->GetContainerWindow()); keyboard_container->SetBounds(root_bounds); root_window()->AddChild(keyboard_container.get()); keyboard_container->Show(); - ShowKeyboard(&controller); + ShowKeyboard(); EXPECT_TRUE(window->IsVisible()); EXPECT_TRUE(keyboard_container->IsVisible()); @@ -244,7 +272,7 @@ TEST_F(KeyboardControllerTest, ClickDoesNotFocusKeyboard) { keyboard_container->AddPreTargetHandler(&observer); aura::test::EventGenerator generator(root_window()); - generator.MoveMouseTo(proxy->GetKeyboardWindow()->bounds().CenterPoint()); + generator.MoveMouseTo(proxy()->GetKeyboardWindow()->bounds().CenterPoint()); generator.ClickLeftButton(); EXPECT_TRUE(window->HasFocus()); EXPECT_FALSE(keyboard_container->HasFocus()); @@ -260,32 +288,43 @@ TEST_F(KeyboardControllerTest, ClickDoesNotFocusKeyboard) { TEST_F(KeyboardControllerTest, VisibilityChangeWithTextInputTypeChange) { const gfx::Rect& root_bounds = root_window()->bounds(); - aura::test::EventCountDelegate delegate; - scoped_ptr<aura::Window> window(new aura::Window(&delegate)); - window->Init(ui::LAYER_NOT_DRAWN); - window->SetBounds(root_bounds); - root_window()->AddChild(window.get()); - window->Show(); - window->Focus(); - - KeyboardControllerProxy* proxy = new TestKeyboardControllerProxy(); - ui::InputMethod* input_method = proxy->GetInputMethod(); - TestTextInputClient input_client(ui::TEXT_INPUT_TYPE_TEXT); - TestTextInputClient no_input_client(ui::TEXT_INPUT_TYPE_NONE); - input_method->SetFocusedTextInputClient(&input_client); - KeyboardController controller(proxy); - - scoped_ptr<aura::Window> keyboard_container(controller.GetContainerWindow()); + ui::InputMethod* input_method = proxy()->GetInputMethod(); + TestTextInputClient input_client_0(ui::TEXT_INPUT_TYPE_TEXT); + TestTextInputClient input_client_1(ui::TEXT_INPUT_TYPE_TEXT); + TestTextInputClient input_client_2(ui::TEXT_INPUT_TYPE_TEXT); + TestTextInputClient no_input_client_0(ui::TEXT_INPUT_TYPE_NONE); + TestTextInputClient no_input_client_1(ui::TEXT_INPUT_TYPE_NONE); + input_method->SetFocusedTextInputClient(&input_client_0); + + scoped_ptr<aura::Window> keyboard_container( + controller()->GetContainerWindow()); + scoped_ptr<KeyboardContainerObserver> keyboard_container_observer( + new KeyboardContainerObserver(keyboard_container.get())); keyboard_container->SetBounds(root_bounds); root_window()->AddChild(keyboard_container.get()); EXPECT_TRUE(keyboard_container->IsVisible()); - input_method->SetFocusedTextInputClient(&no_input_client); + input_method->SetFocusedTextInputClient(&no_input_client_0); + // Keyboard should not immediately hide itself. It is delayed to avoid layout + // flicker when the focus of input field quickly change. + EXPECT_TRUE(keyboard_container->IsVisible()); + EXPECT_TRUE(WillHideKeyboard()); + // Wait for hide keyboard to finish. + base::MessageLoop::current()->Run(); EXPECT_FALSE(keyboard_container->IsVisible()); - input_method->SetFocusedTextInputClient(&input_client); + input_method->SetFocusedTextInputClient(&input_client_1); + EXPECT_TRUE(keyboard_container->IsVisible()); + + // Schedule to hide keyboard. + input_method->SetFocusedTextInputClient(&no_input_client_1); + EXPECT_TRUE(WillHideKeyboard()); + // Cancel keyboard hide. + input_method->SetFocusedTextInputClient(&input_client_2); + + EXPECT_FALSE(WillHideKeyboard()); EXPECT_TRUE(keyboard_container->IsVisible()); } diff --git a/chromium/ui/keyboard/keyboard_resources.grd b/chromium/ui/keyboard/keyboard_resources.grd index 2509d68dc64..8e3da16b8ab 100644 --- a/chromium/ui/keyboard/keyboard_resources.grd +++ b/chromium/ui/keyboard/keyboard_resources.grd @@ -23,11 +23,13 @@ <include name="IDR_KEYBOARD_ELEMENTS_ALTKEY_SET" file="resources/elements/kb-altkey-set.html" type="BINDATA" /> <include name="IDR_KEYBOARD_ELEMENTS_KEY" file="resources/elements/kb-key.html" type="BINDATA" /> <include name="IDR_KEYBOARD_ELEMENTS_KEY_BASE" file="resources/elements/kb-key-base.html" type="BINDATA" /> + <include name="IDR_KEYBOARD_ELEMENTS_KEY_CODES" file="resources/elements/kb-key-codes.html" type="BINDATA" /> <include name="IDR_KEYBOARD_ELEMENTS_KEY_IMPORT" file="resources/elements/kb-key-import.html" type="BINDATA" /> <include name="IDR_KEYBOARD_ELEMENTS_KEY_SEQUENCE" file="resources/elements/kb-key-sequence.html" type="BINDATA" /> <include name="IDR_KEYBOARD_ELEMENTS_KEYBOARD" file="resources/elements/kb-keyboard.html" type="BINDATA" /> <include name="IDR_KEYBOARD_ELEMENTS_KEYSET" file="resources/elements/kb-keyset.html" type="BINDATA" /> <include name="IDR_KEYBOARD_ELEMENTS_ROW" file="resources/elements/kb-row.html" type="BINDATA" /> + <include name="IDR_KEYBOARD_ELEMENTS_SHIFT_KEY" file="resources/elements/kb-shift-key.html" type="BINDATA" /> <include name="IDR_KEYBOARD_IMAGES_KEYBOARD" file="resources/images/keyboard.svg" type="BINDATA" /> <include name="IDR_KEYBOARD_IMAGES_MICROPHONE" file="resources/images/microphone.svg" type="BINDATA" /> <include name="IDR_KEYBOARD_IMAGES_MICROPHONE_GREEN" file="resources/images/microphone-green.svg" type="BINDATA" /> @@ -35,6 +37,7 @@ <include name="IDR_KEYBOARD_INDEX" file="resources/index.html" allowexternalscript="true" type="BINDATA" /> <include name="IDR_KEYBOARD_LAYOUTS_DVORAK" file="resources/layouts/dvorak.html" type="BINDATA" /> <include name="IDR_KEYBOARD_LAYOUTS_LATIN_ACCENTS" file="resources/layouts/latin-accents.js" type="BINDATA" /> + <include name="IDR_KEYBOARD_LAYOUTS_NUMERIC" file="resources/layouts/numeric.html" type="BINDATA" /> <include name="IDR_KEYBOARD_LAYOUTS_QWERTY" file="resources/layouts/qwerty.html" type="BINDATA" /> <include name="IDR_KEYBOARD_LAYOUTS_SYMBOL_ALTKEYS" file="resources/layouts/symbol-altkeys.js" type="BINDATA" /> <include name="IDR_KEYBOARD_MAIN_JS" file="resources/main.js" type="BINDATA" /> diff --git a/chromium/ui/keyboard/keyboard_ui_controller.cc b/chromium/ui/keyboard/keyboard_ui_controller.cc index 1ee8d40a43b..8bc009202d0 100644 --- a/chromium/ui/keyboard/keyboard_ui_controller.cc +++ b/chromium/ui/keyboard/keyboard_ui_controller.cc @@ -30,17 +30,22 @@ content::WebUIDataSource* CreateKeyboardUIDataSource() { source->AddResourcePath("elements/kb-key.html", IDR_KEYBOARD_ELEMENTS_KEY); source->AddResourcePath("elements/kb-key-base.html", IDR_KEYBOARD_ELEMENTS_KEY_BASE); + source->AddResourcePath("elements/kb-key-codes.html", + IDR_KEYBOARD_ELEMENTS_KEY_CODES); source->AddResourcePath("elements/kb-keyboard.html", IDR_KEYBOARD_ELEMENTS_KEYBOARD); source->AddResourcePath("elements/kb-keyset.html", IDR_KEYBOARD_ELEMENTS_KEYSET); source->AddResourcePath("elements/kb-row.html", IDR_KEYBOARD_ELEMENTS_ROW); + source->AddResourcePath("elements/kb-shift-key.html", + IDR_KEYBOARD_ELEMENTS_SHIFT_KEY); source->AddResourcePath("images/microphone.svg", IDR_KEYBOARD_IMAGES_MICROPHONE); source->AddResourcePath("images/microphone-green.svg", IDR_KEYBOARD_IMAGES_MICROPHONE_GREEN); source->AddResourcePath("layouts/latin-accents.js", IDR_KEYBOARD_LAYOUTS_LATIN_ACCENTS); + source->AddResourcePath("layouts/numeric.html", IDR_KEYBOARD_LAYOUTS_NUMERIC); source->AddResourcePath("main.js", IDR_KEYBOARD_MAIN_JS); source->AddResourcePath("polymer.min.js", IDR_KEYBOARD_POLYMER); source->AddResourcePath("voice_input.js", IDR_KEYBOARD_VOICE_INPUT_JS); diff --git a/chromium/ui/keyboard/keyboard_ui_handler.cc b/chromium/ui/keyboard/keyboard_ui_handler.cc index 0c412675d3e..26909c2d49e 100644 --- a/chromium/ui/keyboard/keyboard_ui_handler.cc +++ b/chromium/ui/keyboard/keyboard_ui_handler.cc @@ -12,7 +12,12 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_view.h" #include "content/public/browser/web_ui.h" +#include "ui/aura/client/aura_constants.h" +#include "ui/aura/root_window.h" #include "ui/aura/window.h" +#include "ui/base/ime/input_method.h" +#include "ui/base/ime/text_input_client.h" +#include "ui/keyboard/keyboard_controller.h" #include "ui/keyboard/keyboard_util.h" namespace keyboard { @@ -28,6 +33,18 @@ void KeyboardUIHandler::RegisterMessages() { "insertText", base::Bind(&KeyboardUIHandler::HandleInsertTextMessage, base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "getInputContext", + base::Bind(&KeyboardUIHandler::HandleGetInputContextMessage, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "sendKeyEvent", + base::Bind(&KeyboardUIHandler::HandleSendKeyEventMessage, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "hideKeyboard", + base::Bind(&KeyboardUIHandler::HandleHideKeyboard, + base::Unretained(this))); } void KeyboardUIHandler::HandleInsertTextMessage(const base::ListValue* args) { @@ -48,4 +65,75 @@ void KeyboardUIHandler::HandleInsertTextMessage(const base::ListValue* args) { LOG(ERROR) << "insertText failed"; } +void KeyboardUIHandler::HandleGetInputContextMessage( + const base::ListValue* args) { + int request_id; + if (!args->GetInteger(0, &request_id)) { + LOG(ERROR) << "getInputContext failed: bad argument"; + return; + } + base::DictionaryValue results; + results.SetInteger("requestId", request_id); + + aura::RootWindow* root_window = + web_ui()->GetWebContents()->GetView()->GetNativeView()->GetRootWindow(); + if (!root_window) { + LOG(ERROR) << "getInputContext failed: no root window"; + return; + } + ui::InputMethod* input_method = + root_window->GetProperty(aura::client::kRootWindowInputMethodKey); + if (!input_method) { + LOG(ERROR) << "getInputContext failed: no input method"; + return; + } + + ui::TextInputClient* tic = input_method->GetTextInputClient(); + results.SetInteger("type", + tic ? tic->GetTextInputType() : ui::TEXT_INPUT_TYPE_NONE); + + web_ui()->CallJavascriptFunction("GetInputContextCallback", + results); +} + +void KeyboardUIHandler::HandleSendKeyEventMessage( + const base::ListValue* args) { + const base::DictionaryValue* params = NULL; + std::string type; + int char_value; + int key_code; + bool shift_modifier; + + if (!args->GetDictionary(0, ¶ms) || + !params->GetString("type", &type) || + !params->GetInteger("charValue", &char_value) || + !params->GetInteger("keyCode", &key_code) || + !params->GetBoolean("shiftKey", &shift_modifier)) { + LOG(ERROR) << "SendKeyEvent failed: bad argument"; + return; + } + + aura::RootWindow* root_window = + web_ui()->GetWebContents()->GetView()->GetNativeView()->GetRootWindow(); + if (!root_window) { + LOG(ERROR) << "sendKeyEvent failed: no root window"; + return; + } + + if (!keyboard::SendKeyEvent(type, + char_value, + key_code, + shift_modifier, + root_window)) { + LOG(ERROR) << "sendKeyEvent failed"; + } +} + +void KeyboardUIHandler::HandleHideKeyboard(const base::ListValue* args) { + // TODO(stevet): Call into the keyboard controller to hide the keyboard + // directly. + NOTIMPLEMENTED(); + return; +} + } // namespace keyboard diff --git a/chromium/ui/keyboard/keyboard_ui_handler.h b/chromium/ui/keyboard/keyboard_ui_handler.h index 0800453192d..3c14f7473e5 100644 --- a/chromium/ui/keyboard/keyboard_ui_handler.h +++ b/chromium/ui/keyboard/keyboard_ui_handler.h @@ -25,6 +25,18 @@ class KeyboardUIHandler : public content::WebUIMessageHandler { // Callback for the "insertText" message. void HandleInsertTextMessage(const base::ListValue* args); + // Callback for the "getInputContext" message. The first element in + // |args| should be an integer representing request ID. + void HandleGetInputContextMessage(const base::ListValue* args); + + // Callback for the "sendKeyEvent" message. The first element in |args| is a + // dictionary containing an event type, the character being pressed or + // released, a virtual key code, and the state of the shift key. + void HandleSendKeyEventMessage(const base::ListValue* args); + + // Callback for the "hideKeyboard" message. + void HandleHideKeyboard(const base::ListValue* args); + DISALLOW_COPY_AND_ASSIGN(KeyboardUIHandler); }; diff --git a/chromium/ui/keyboard/keyboard_util.cc b/chromium/ui/keyboard/keyboard_util.cc index 1579068f884..8389e55f03b 100644 --- a/chromium/ui/keyboard/keyboard_util.cc +++ b/chromium/ui/keyboard/keyboard_util.cc @@ -17,6 +17,20 @@ #include "ui/base/ime/text_input_client.h" #include "ui/keyboard/keyboard_switches.h" +namespace { + +const char kKeyDown[] ="keydown"; +const char kKeyUp[] = "keyup"; + +void SendProcessKeyEvent(ui::EventType type, aura::RootWindow* root_window) { + ui::TranslatedKeyEvent event(type == ui::ET_KEY_PRESSED, + ui::VKEY_PROCESSKEY, + ui::EF_NONE); + root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&event); +} + +} // namespace + namespace keyboard { bool IsKeyboardEnabled() { @@ -28,28 +42,6 @@ bool InsertText(const base::string16& text, aura::RootWindow* root_window) { if (!root_window) return false; - // Handle Backspace and Enter specially: using TextInputClient::InsertText is - // very unreliable for these characters. - // TODO(bryeung): remove this code once virtual keyboards are able to send - // these events directly via the Input Injection API. - if (text.length() == 1) { - ui::KeyboardCode code = ui::VKEY_UNKNOWN; - if (text[0] == L'\n') - code = ui::VKEY_RETURN; - else if (text[0] == L'\b') - code = ui::VKEY_BACK; - - if (code != ui::VKEY_UNKNOWN) { - ui::KeyEvent press_event(ui::ET_KEY_PRESSED, code, 0, 0); - root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&press_event); - - ui::KeyEvent release_event(ui::ET_KEY_RELEASED, code, 0, 0); - root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&release_event); - - return true; - } - } - ui::InputMethod* input_method = root_window->GetProperty( aura::client::kRootWindowInputMethodKey); if (!input_method) @@ -103,6 +95,47 @@ bool MoveCursor(int swipe_direction, return true; } +bool SendKeyEvent(const std::string type, + int key_value, + int key_code, + bool shift_modifier, + aura::RootWindow* root_window) { + ui::EventType event_type = ui::ET_UNKNOWN; + if (type == kKeyDown) + event_type = ui::ET_KEY_PRESSED; + else if (type == kKeyUp) + event_type = ui::ET_KEY_RELEASED; + if (event_type == ui::ET_UNKNOWN) + return false; + + int flags = ui::EF_NONE; + if (shift_modifier) + flags = ui::EF_SHIFT_DOWN; + + ui::KeyboardCode code = static_cast<ui::KeyboardCode>(key_code); + + if (code == ui::VKEY_UNKNOWN) { + // Handling of special printable characters (e.g. accented characters) for + // which there is no key code. + if (event_type == ui::ET_KEY_RELEASED) { + ui::InputMethod* input_method = root_window->GetProperty( + aura::client::kRootWindowInputMethodKey); + if (!input_method) + return false; + + ui::TextInputClient* tic = input_method->GetTextInputClient(); + + SendProcessKeyEvent(ui::ET_KEY_PRESSED, root_window); + tic->InsertChar(static_cast<uint16>(key_value), ui::EF_NONE); + SendProcessKeyEvent(ui::ET_KEY_RELEASED, root_window); + } + } else { + ui::KeyEvent event(event_type, code, flags, false); + root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&event); + } + return true; +} + const GritResourceMap* GetKeyboardExtensionResources(size_t* size) { // This looks a lot like the contents of a resource map; however it is // necessary to have a custom path for the extension path, so the resource @@ -118,6 +151,7 @@ const GritResourceMap* GetKeyboardExtensionResources(size_t* size) { {"keyboard/elements/kb-altkey-set.html", IDR_KEYBOARD_ELEMENTS_ALTKEY_SET}, {"keyboard/elements/kb-key.html", IDR_KEYBOARD_ELEMENTS_KEY}, {"keyboard/elements/kb-key-base.html", IDR_KEYBOARD_ELEMENTS_KEY_BASE}, + {"keyboard/elements/kb-key-codes.html", IDR_KEYBOARD_ELEMENTS_KEY_CODES}, {"keyboard/elements/kb-key-import.html", IDR_KEYBOARD_ELEMENTS_KEY_IMPORT}, {"keyboard/elements/kb-key-sequence.html", @@ -125,6 +159,7 @@ const GritResourceMap* GetKeyboardExtensionResources(size_t* size) { {"keyboard/elements/kb-keyboard.html", IDR_KEYBOARD_ELEMENTS_KEYBOARD}, {"keyboard/elements/kb-keyset.html", IDR_KEYBOARD_ELEMENTS_KEYSET}, {"keyboard/elements/kb-row.html", IDR_KEYBOARD_ELEMENTS_ROW}, + {"keyboard/elements/kb-shift-key.html", IDR_KEYBOARD_ELEMENTS_SHIFT_KEY}, {"keyboard/images/keyboard.svg", IDR_KEYBOARD_IMAGES_KEYBOARD}, {"keyboard/images/microphone.svg", IDR_KEYBOARD_IMAGES_MICROPHONE}, {"keyboard/images/microphone-green.svg", @@ -132,6 +167,7 @@ const GritResourceMap* GetKeyboardExtensionResources(size_t* size) { {"keyboard/index.html", IDR_KEYBOARD_INDEX}, {"keyboard/layouts/dvorak.html", IDR_KEYBOARD_LAYOUTS_DVORAK}, {"keyboard/layouts/latin-accents.js", IDR_KEYBOARD_LAYOUTS_LATIN_ACCENTS}, + {"keyboard/layouts/numeric.html", IDR_KEYBOARD_LAYOUTS_NUMERIC}, {"keyboard/layouts/qwerty.html", IDR_KEYBOARD_LAYOUTS_QWERTY}, {"keyboard/layouts/symbol-altkeys.js", IDR_KEYBOARD_LAYOUTS_SYMBOL_ALTKEYS}, diff --git a/chromium/ui/keyboard/keyboard_util.h b/chromium/ui/keyboard/keyboard_util.h index 7d4643335c9..bb0edfb7bd7 100644 --- a/chromium/ui/keyboard/keyboard_util.h +++ b/chromium/ui/keyboard/keyboard_util.h @@ -29,7 +29,7 @@ enum CursorMoveDirection { KEYBOARD_EXPORT bool IsKeyboardEnabled(); // Insert |text| into the active TextInputClient associated with |root_window|, -// if there is one. Returns true if |text| was successfully inserted. Note +// if there is one. Returns true if |text| was successfully inserted. Note // that this may convert |text| into ui::KeyEvents for injection in some // special circumstances (i.e. VKEY_RETURN, VKEY_BACK). KEYBOARD_EXPORT bool InsertText(const base::string16& text, @@ -41,7 +41,18 @@ KEYBOARD_EXPORT bool MoveCursor(int swipe_direction, int modifier_flags, aura::RootWindow* root_window); -// Get the list of keyboard resources. |size| is populated with the number of +// Sends a fabricated key event, where |type| is the event type, |key_value| +// is the unicode value of the character, |key_code| is the legacy key code +// value, and |shift_modifier| indicates if the shift key is being virtually +// pressed. The event is dispatched to the active TextInputClient associated +// with |root_window|. The type may be "keydown" or "keyup". +KEYBOARD_EXPORT bool SendKeyEvent(std::string type, + int key_value, + int key_code, + bool shift_modifier, + aura::RootWindow* root_window); + +// Get the list of keyboard resources. |size| is populated with the number of // resources in the returned array. KEYBOARD_EXPORT const GritResourceMap* GetKeyboardExtensionResources( size_t* size); diff --git a/chromium/ui/keyboard/resources/OWNERS b/chromium/ui/keyboard/resources/OWNERS index eca3960110e..7a6ff670440 100644 --- a/chromium/ui/keyboard/resources/OWNERS +++ b/chromium/ui/keyboard/resources/OWNERS @@ -1,2 +1,3 @@ bryeung@chromium.org bshe@chromium.org +kevers@chromium.org diff --git a/chromium/ui/keyboard/resources/api_adapter.js b/chromium/ui/keyboard/resources/api_adapter.js index eb95e35cb8b..049c3666242 100644 --- a/chromium/ui/keyboard/resources/api_adapter.js +++ b/chromium/ui/keyboard/resources/api_adapter.js @@ -1,4 +1,4 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// 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. @@ -9,10 +9,23 @@ function logIfError() { } function insertText(text) { - chrome.experimental.input.virtualKeyboard.insertText(text, logIfError); + chrome.virtualKeyboardPrivate.insertText(text, logIfError); } function MoveCursor(swipe_direction, swipe_flags) { - chrome.experimental.input.virtualKeyboard.moveCursor(swipe_direction, - swipe_flags); + chrome.virtualKeyboardPrivate.moveCursor(swipe_direction, swipe_flags); } + +function sendKeyEvent(event) { + chrome.virtualKeyboardPrivate.sendKeyEvent(event, logIfError); +} + +function hideKeyboard() { + chrome.virtualKeyboardPrivate.hideKeyboard(logIfError); +} + +chrome.virtualKeyboardPrivate.onTextInputBoxFocused.addListener( + function (inputContext) { + // TODO(bshe): Making keyboard aware of inputContext. + } +); diff --git a/chromium/ui/keyboard/resources/elements/kb-altkey-data.html b/chromium/ui/keyboard/resources/elements/kb-altkey-data.html index 8f8b9a96420..67f793ad4b1 100644 --- a/chromium/ui/keyboard/resources/elements/kb-altkey-data.html +++ b/chromium/ui/keyboard/resources/elements/kb-altkey-data.html @@ -10,8 +10,21 @@ var altKeys = {}; var idMap = {}; - function createId(char) { - return 'id' + char.charCodeAt(0); + /** + * Creates a unique identifier based on the key provided. + * This identifier is of the form 'idHASH' where HASH is + * the concatenation of the keycodes of every character in the string. + * @param {string} key Key for which we want an identifier. + * @return {string} The unique id for key. + */ + function createId(key) { + var hash = key.split('').map( + // Returns the key code for the character. + function(character) { + return character.charCodeAt(0); + } + ).join(''); + return 'id' + hash; } Polymer('kb-altkey-data', { @@ -21,7 +34,7 @@ * @param {string} char The base character. * @param {boolean=} opt_force If true, force the creation of a list * even if empty. Used when constructing a set of alternates for keys - * with superscripts. + * with hintTexts. * @return {?Object.{id: string, list: string}} */ getAltkeys: function(char, opt_force) { diff --git a/chromium/ui/keyboard/resources/elements/kb-key-base.html b/chromium/ui/keyboard/resources/elements/kb-key-base.html index 497da30f6c4..89a174809d3 100644 --- a/chromium/ui/keyboard/resources/elements/kb-key-base.html +++ b/chromium/ui/keyboard/resources/elements/kb-key-base.html @@ -6,7 +6,7 @@ <polymer-element name="kb-key-base" on-pointerdown="down" on-pointerup="up" on-pointerout="out" - attributes="accents char invert repeat superscript toKeyset toLayout"> + attributes="accents char invert repeat hintText toKeyset toLayout"> <script> /** * The long-press delay in milliseconds before long-press handler is @@ -109,43 +109,58 @@ } }, down: function(event) { - var detail = { - char: this.char || this.textContent, - toLayout: this.toLayout, - repeat: this.repeat - }; + var detail = this.populateDetails(); if (this.keysetRules && this.keysetRules.down != undefined) { detail.toKeyset = this.keysetRules.down[TO_KEYSET - OFFSET]; detail.nextKeyset = this.keysetRules.down[NEXT_KEYSET - OFFSET]; } this.fire('key-down', detail); - this.longPressTimer = this.asyncMethod(function() { - var detail = { - char: this.char || this.textContent, - superscript: this.superscript - }; - if (this.keysetRules && this.keysetRules.long != undefined) { - detail.toKeyset = this.keysetRules.long[TO_KEYSET - OFFSET]; - detail.nextKeyset = this.keysetRules.long[NEXT_KEYSET - OFFSET]; - } - this.fire('key-longpress', detail); - }, null, LONGPRESS_DELAY_MSEC); + this.longPressTimer = this.generateLongPressTimer(); }, out: function(event) { clearTimeout(this.longPressTimer); }, up: function(event) { clearTimeout(this.longPressTimer); - var detail = { - char: this.char || this.textContent, - toLayout: this.toLayout - }; + var detail = this.populateDetails(); if (this.keysetRules && this.keysetRules.up != undefined) { detail.toKeyset = this.keysetRules.up[TO_KEYSET - OFFSET]; detail.nextKeyset = this.keysetRules.up[NEXT_KEYSET - OFFSET]; } this.fire('key-up', detail); - } + }, + + /** + * Character value associated with the key. Typically, the value is a + * single charcater, but may be multi-character in cases like a ".com" + * button. + * @type {string} + */ + get charValue() { + return this.char || this.textContent; + }, + + populateDetails: function() { + return { + char: this.charValue, + toLayout: this.toLayout, + repeat: this.repeat + }; + }, + + generateLongPressTimer: function() { + return this.asyncMethod(function() { + var detail = { + char: this.charValue, + hintText: this.hintText + }; + if (this.keysetRules && this.keysetRules.long != undefined) { + detail.toKeyset = this.keysetRules.long[TO_KEYSET - OFFSET]; + detail.nextKeyset = this.keysetRules.long[NEXT_KEYSET - OFFSET]; + } + this.fire('key-longpress', detail); + }, null, LONGPRESS_DELAY_MSEC); + }, }); </script> </polymer-element> diff --git a/chromium/ui/keyboard/resources/elements/kb-key-codes.html b/chromium/ui/keyboard/resources/elements/kb-key-codes.html new file mode 100644 index 00000000000..b8353ecd938 --- /dev/null +++ b/chromium/ui/keyboard/resources/elements/kb-key-codes.html @@ -0,0 +1,180 @@ +<!-- + -- 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. + --> + +<polymer-element name="kb-key-codes"> +<script> + (function() { + // Each virtual key event is assigned a unique ID. + var nextRequestID = 0; + + // Keycodes have been deprecated in the KeyEvent specification, but are + // nonetheless required to support legacy web content. The Keycodes in the + // following table are based on subset of US-EN 101-key keyboard. These + // codes are used in the absence of explicit keycodes for kb-key and + // kb-keysequence elements. Keyboard layout authors may explicitly set the + // keyCode attribute for kb-key or kb-keysequence elements to refer to + // indices in this table in order to emulate a physical keyboard with an + // alternate layout. Not all keys on a virtual keyboard are required to + // have keyCodes. + var keyCodes = { + '\b': {keyCode: 0x08, shiftModifier: false}, + '\t': {keyCode: 0x09, shiftModifier: false}, + '\n': {keyCode: 0x0D, shiftModifier: false}, + ' ': {keyCode: 0x20, shiftModifier: false}, + '0': {keyCode: 0x30, shiftModifier: false}, + ')': {keyCode: 0x30, shiftModifier: true}, + '1': {keyCode: 0x31, shiftModifier: false}, + '!': {keyCode: 0x31, shiftModifier: true}, + '2': {keyCode: 0x32, shiftModifier: false}, + '@': {keyCode: 0x32, shiftModifier: true}, + '3': {keyCode: 0x33, shiftModifier: false}, + '#': {keyCode: 0x33, shiftModifier: true}, + '4': {keyCode: 0x34, shiftModifier: false}, + '$': {keyCode: 0x34, shiftModifier: true}, + '5': {keyCode: 0x35, shiftModifier: false}, + '%': {keyCode: 0x35, shiftModifier: true}, + '6': {keyCode: 0x36, shiftModifier: false}, + '^': {keyCode: 0x36, shiftModifier: true}, + '7': {keyCode: 0x37, shiftModifier: false}, + '&': {keyCode: 0x37, shiftModifier: true}, + '8': {keyCode: 0x38, shiftModifier: false}, + '*': {keyCode: 0x38, shiftModifier: true}, + '9': {keyCode: 0x39, shiftModifier: false}, + '(': {keyCode: 0x39, shiftModifier: true}, + 'a': {keyCode: 0x41, shiftModifier: false}, + 'A': {keyCode: 0x41, shiftModifier: true}, + 'b': {keyCode: 0x42, shiftModifier: false}, + 'B': {keyCode: 0x42, shiftModifier: true}, + 'c': {keyCode: 0x43, shiftModifier: false}, + 'C': {keyCode: 0x43, shiftModifier: true}, + 'd': {keyCode: 0x44, shiftModifier: false}, + 'D': {keyCode: 0x44, shiftModifier: true}, + 'e': {keyCode: 0x45, shiftModifier: false}, + 'E': {keyCode: 0x45, shiftModifier: true}, + 'f': {keyCode: 0x46, shiftModifier: false}, + 'F': {keyCode: 0x46, shiftModifier: true}, + 'g': {keyCode: 0x47, shiftModifier: false}, + 'G': {keyCode: 0x47, shiftModifier: true}, + 'h': {keyCode: 0x48, shiftModifier: false}, + 'H': {keyCode: 0x48, shiftModifier: true}, + 'i': {keyCode: 0x49, shiftModifier: false}, + 'I': {keyCode: 0x49, shiftModifier: true}, + 'j': {keyCode: 0x4A, shiftModifier: false}, + 'J': {keyCode: 0x4A, shiftModifier: true}, + 'k': {keyCode: 0x4B, shiftModifier: false}, + 'K': {keyCode: 0x4B, shiftModifier: true}, + 'l': {keyCode: 0x4C, shiftModifier: false}, + 'L': {keyCode: 0x4C, shiftModifier: true}, + 'm': {keyCode: 0x4D, shiftModifier: false}, + 'M': {keyCode: 0x4D, shiftModifier: true}, + 'n': {keyCode: 0x4E, shiftModifier: false}, + 'N': {keyCode: 0x4E, shiftModifier: true}, + 'o': {keyCode: 0x4F, shiftModifier: false}, + 'O': {keyCode: 0x4F, shiftModifier: true}, + 'p': {keyCode: 0x50, shiftModifier: false}, + 'P': {keyCode: 0x50, shiftModifier: true}, + 'q': {keyCode: 0x51, shiftModifier: false}, + 'Q': {keyCode: 0x51, shiftModifier: true}, + 'r': {keyCode: 0x52, shiftModifier: false}, + 'R': {keyCode: 0x52, shiftModifier: true}, + 's': {keyCode: 0x53, shiftModifier: false}, + 'S': {keyCode: 0x53, shiftModifier: true}, + 't': {keyCode: 0x54, shiftModifier: false}, + 'T': {keyCode: 0x54, shiftModifier: true}, + 'u': {keyCode: 0x55, shiftModifier: false}, + 'U': {keyCode: 0x55, shiftModifier: true}, + 'v': {keyCode: 0x56, shiftModifier: false}, + 'V': {keyCode: 0x56, shiftModifier: true}, + 'w': {keyCode: 0x57, shiftModifier: false}, + 'W': {keyCode: 0x57, shiftModifier: true}, + 'x': {keyCode: 0x58, shiftModifier: false}, + 'X': {keyCode: 0x58, shiftModifier: true}, + 'y': {keyCode: 0x59, shiftModifier: false}, + 'Y': {keyCode: 0x59, shiftModifier: true}, + 'z': {keyCode: 0x5A, shiftModifier: false}, + 'Z': {keyCode: 0x5A, shiftModifier: true}, + ';': {keyCode: 0xBA, shiftModifier: false}, + ':': {keyCode: 0xBA, shiftModifier: true}, + '=': {keyCode: 0xBB, shiftModifier: false}, + '+': {keyCode: 0xBB, shiftModifier: true}, + ',': {keyCode: 0xBC, shiftModifier: false}, + '<': {keyCode: 0xBC, shiftModifier: true}, + '-': {keyCode: 0xBD, shiftModifier: false}, + '_': {keyCode: 0xBD, shiftModifier: true}, + '.': {keyCode: 0xBE, shiftModifier: false}, + '>': {keyCode: 0xBE, shiftModifier: true}, + '/': {keyCode: 0xBF, shiftModifier: false}, + '?': {keyCode: 0xBF, shiftModifier: true}, + '`': {keyCode: 0xC0, shiftModifier: false}, + '~': {keyCode: 0xC0, shiftModifier: true}, + '[': {keyCode: 0xDB, shiftModifier: false}, + '{': {keyCode: 0xDB, shiftModifier: true}, + '\\': {keyCode: 0xDC, shiftModifier: false}, + '|': {keyCode: 0xDC, shiftModifier: true}, + ']': {keyCode: 0xDD, shiftModifier: false}, + '}': {keyCode: 0xDD, shiftModifier: true}, + '\'': {keyCode: 0xDE, shiftModifier: false}, + '"': {keyCode: 0xDE, shiftModifier: true}, + }; + + Polymer('kb-key-codes', { + /** + * Retrieves the keyCode and status of the shift modifier. + * @param {string} id ID of an entry in the code table. + * @return {keyCode: numeric, shiftModifier: boolean} + */ + GetKeyCodeAndModifiers: function(id) { + var entry = keyCodes[id]; + if (entry) { + return { + keyCode: entry.keyCode, + shiftModifier: entry.shiftModifier + }; + } + return { + keyCode: 0, + shiftModifier: false + }; + }, + + /** + * Creates a virtual key event for use with the keyboard extension API. + * See http://www.w3.org/TR/DOM-Level-3-Events/#events-KeyboardEvent. + * @param {Object} detail Attribute of the key being pressed or released. + * @param {string} type The type of key event, which may be keydown + * or keyup. + * @return {?KeyboardEvent} A KeyboardEvent object, or undefined on + * failure. + */ + createVirtualKeyEvent: function(detail, type) { + var char = detail.char; + if (!char || char.length != 1) { + console.error('Invalid key. Expected single character.'); + return; + } + var keyCode = detail.keyCode; + var shiftModifier = detail.shiftModifier; + if (keyCode == undefined) { + var state = this.GetKeyCodeAndModifiers(char); + if (state) { + keyCode = state.keyCode; + shiftModifier = state.shiftModifier; + } else { + keyCode = 0; + shiftModifier = false; + } + } + return { + type: type, + charValue: char.charCodeAt(0), + keyCode: keyCode, + shiftKey: shiftModifier + }; + }, + }); + })(); +</script> +</polymer-element> diff --git a/chromium/ui/keyboard/resources/elements/kb-key-sequence.html b/chromium/ui/keyboard/resources/elements/kb-key-sequence.html index dee295bec3b..ad01003b2a1 100644 --- a/chromium/ui/keyboard/resources/elements/kb-key-sequence.html +++ b/chromium/ui/keyboard/resources/elements/kb-key-sequence.html @@ -4,7 +4,7 @@ -- found in the LICENSE file. --> -<polymer-element name="kb-key-sequence" attributes="keys superscripts"> +<polymer-element name="kb-key-sequence" attributes="keys hintTexts keyCodes"> <template> <style> @host { @@ -13,6 +13,7 @@ } } </style> + <kb-key-codes id="keyCodeMetadata"></kb-key-codes> </template> <script> Polymer('kb-key-sequence', { @@ -23,9 +24,14 @@ var result; if (this.keys) { var newKeys = this.keys; - var newSuperScripts = this.superscripts; - if (newSuperScripts && newKeys.length != newSuperScripts.length) { - console.error('keys and superscripts do not match'); + var newHintTexts = this.hintTexts; + if (newHintTexts && newKeys.length != newHintTexts.length) { + console.error('keys and hintTexts do not match'); + return; + } + var keyCodes = this.keyCodes || newKeys; + if (keyCodes && newKeys.length != keyCodes.length) { + console.error('keys and keyCodes do not match'); return; } var replacement = document.createDocumentFragment(); @@ -33,8 +39,14 @@ var key = document.createElement('kb-key'); key.innerText = newKeys[i]; key.accents = newKeys[i]; - if (newSuperScripts) - key.superscript = newSuperScripts[i]; + if (newHintTexts) + key.hintText = newHintTexts[i]; + var state = this.$.keyCodeMetadata.GetKeyCodeAndModifiers( + keyCodes[i]); + if (state) { + key.keyCode = state.keyCode; + key.shiftModifier = state.shiftModifier; + } replacement.appendChild(key); } result = replacement; diff --git a/chromium/ui/keyboard/resources/elements/kb-key.html b/chromium/ui/keyboard/resources/elements/kb-key.html index fc366bbee92..d9bf0776750 100644 --- a/chromium/ui/keyboard/resources/elements/kb-key.html +++ b/chromium/ui/keyboard/resources/elements/kb-key.html @@ -4,7 +4,8 @@ -- found in the LICENSE file. --> -<polymer-element name="kb-key" extends="kb-key-base" attributes="weight"> +<polymer-element name="kb-key" extends="kb-key-base" + attributes="keyCode shiftModifier weight"> <template> <style> @host { @@ -16,45 +17,67 @@ <div id="key" pseudo="x-key" inverted?={{invert}}> <content></content> </div> - <div pseudo="x-superscript" inverted?={{invert}}>{{superscript}}</div> + <div pseudo="x-hinttext" inverted?={{invert}}>{{hintText}}</div> </template> <script> Polymer('kb-key', { - weight: 1 + /** + * Key codes have been deprecated in DOM3 key events, but are required + * for legacy web content. The key codes depend on the position of the + * key on the keyboard and is independent of which modifier keys (shift, + * alt, ...) are active. + * @type {number|undefined} + */ + keyCode: undefined, + /** + * Whether the shift key is pressed when producing the key value. + * @type {boolean} + */ + shiftModifier: false, + /** + * Weighting to use for layout in order to properly size the key. + * Keys with a high weighting are wider than normal keys. + * @type {number} + */ + weight: 1, + + /** + * Returns a subset of the key attributes. + * @return {Object} Mapping of attributes for the key element. + */ + populateDetails: function() { + var details = this.super(); + details.keyCode = this.keyCode; + details.shiftModifier = this.shiftModifier; + return details; + }, }); </script> </polymer-element> <!-- Special keys --> -<polymer-element name="kb-shift-key" class="shift dark" char="Shift" +<!-- + -- TODO(kevers): Rip this out if and when we are done implementing the proper + -- layout switcher. + --> +<polymer-element name="kb-layout-selector" class="layout-selector dark" char="Invalid" extends="kb-key"> <script> - Polymer('kb-shift-key', { - down: function(event) { - this.super(); - var detail = {}; - if (this.keysetRules && this.keysetRules.dbl != undefined) { - detail.char = this.char || this.textContent; - detail.toKeyset = this.keysetRules.dbl[TO_KEYSET - OFFSET]; - detail.nextKeyset = this.keysetRules.dbl[NEXT_KEYSET - OFFSET]; - } - this.fire('enable-dbl', detail); - this.fire('enable-sel'); - } + Polymer('kb-layout-selector', { + toLayout: 'qwerty' }); </script> </polymer-element> -<!-- - -- TODO(kevers): Display popup menu for selecting layout on keypress. Display - -- code for keyboard layout in place of image. - --> -<polymer-element name="kb-layout-selector" class="layout-selector dark" char="Invalid" +<polymer-element name="kb-hide-keyboard-key" class="hide-keyboard dark" char="Invalid" extends="kb-key"> <script> - Polymer('kb-layout-selector', { - toLayout: 'qwerty' + Polymer('kb-hide-keyboard-key', { + down: function(event) {}, + up: function(event) { + hideKeyboard(); + } }); </script> </polymer-element> diff --git a/chromium/ui/keyboard/resources/elements/kb-keyboard.html b/chromium/ui/keyboard/resources/elements/kb-keyboard.html index f4efb314084..ea09e372f78 100644 --- a/chromium/ui/keyboard/resources/elements/kb-keyboard.html +++ b/chromium/ui/keyboard/resources/elements/kb-keyboard.html @@ -1,5 +1,5 @@ <!-- - -- Copyright (c) 2013 The Chromium Authors. All rights reserved. + -- 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. --> @@ -7,7 +7,8 @@ <polymer-element name="kb-keyboard" on-key-over="keyOver" on-key-up="keyUp" on-key-down="keyDown" on-key-longpress="keyLongpress" on-pointerup="up" on-pointerdown="down" on-enable-sel="enableSel" - on-enable-dbl="enableDbl" attributes="keyset layout rows"> + on-enable-dbl="enableDbl" + attributes="keyset layout rows inputType inputTypeToLayoutMap"> <template> <style> @host { @@ -23,6 +24,7 @@ -- keyboard layouts. --> <content select="#{{layout}}-{{keyset}}"></content> + <kb-key-codes id="keyCodeMetadata"></kb-key-codes> </template> <script> /** @@ -50,6 +52,20 @@ var DBL_INTERVAL_MSEC = 300; /** + * The index of the name of the keyset when searching for all keysets. + * @const + * @type {number} + */ + var REGEX_KEYSET_INDEX = 1; + + /** + * The integer number of matches when searching for keysets. + * @const + * @type {number} + */ + var REGEX_MATCH_COUNT = 2; + + /** * The boolean to decide if keyboard should transit to upper case keyset * when spacebar is pressed. If a closing punctuation is followed by a * spacebar, keyboard should automatically transit to upper case. @@ -112,7 +128,6 @@ /** * The boolean to decide if it is swipe in process or finished. - * @const * @type {boolean} */ var swipeInProgress = false; @@ -179,6 +194,18 @@ dblDetail_: null, dblTimer_: null, swipeHandler: null, + shift: null, + inputType: null, + + /** + * The default input type to keyboard layout map. The key must be one of + * the input box type values. + * @type {object} + */ + inputTypeToLayoutMap: { + number: "numeric", + text: "qwerty" + }, ready: function() { this.voiceInput_ = new VoiceInput(this); @@ -186,6 +213,20 @@ }, /** + * Called when the type of focused input box changes. If a keyboard layout + * is defined for the current input type, that layout will be loaded. + * Otherwise, the keyboard layout for 'text' type will be loaded. + */ + inputTypeChanged: function() { + // TODO(bshe): Toggle visibility of some keys in a keyboard layout + // according to the input type. + var layout = this.inputTypeToLayoutMap[this.inputType]; + if (!layout) + layout = this.inputTypeToLayoutMap.text; + this.layout = layout; + }, + + /** * When double click/tap event is enabled, the second key-down and key-up * events on the same key should be skipped. Return true when the event * with |detail| should be skipped. @@ -262,6 +303,24 @@ this.lastPressedKey = event.target; this.lastPressedKey.classList.add('active'); repeatKey.cancel(); + + var char = detail.char; + switch(char) { + case 'Shift': + // Removes caps-lock if caps-locked. + if(this.classList.contains('caps-locked')) { + this.classList.remove('caps-locked'); + } + break; + default: + // Non-control key pressed, notify control keys. + // Control keys are shift, control and alt. + if(this.shift) + this.shift.onNonControlKeyDown(); + break; + } + + // A transition key was pressed, immediately move to new keyset. var toKeyset = detail.toKeyset; if (toKeyset) { this.keyset = toKeyset; @@ -271,12 +330,13 @@ } if (detail.repeat) { - insertText(detail.char); + this.keyTyped(detail); repeatKey.key = this.lastPressedKey; + var self = this; repeatKey.timer = setTimeout(function() { repeatKey.timer = undefined; repeatKey.interval = setInterval(function() { - insertText(detail.char); + self.keyTyped(detail); }, REPEAT_INTERVAL_MSEC); }, Math.max(0, REPEAT_DELAY_MSEC - REPEAT_INTERVAL_MSEC)); } @@ -294,6 +354,7 @@ this.dblDetail_.clickCount = 0; var self = this; this.dblTimer_ = setTimeout(function() { + self.dblDetail_.callback = null; self.dblDetail_ = null; }, DBL_INTERVAL_MSEC); } @@ -330,10 +391,15 @@ if (this.dblDetail_) { this.dblDetail_.clickCount++; if (this.dblDetail_.clickCount == 2) { + this.dblDetail_.callback(); this.keyset = this.dblDetail_.toKeyset; - var keysetId = '#' + this.layout + '-' + this.keyset - this.querySelector(keysetId).nextKeyset = this.dblTimer_.nextKeyset; + var keysetId = '#' + this.layout + '-' + this.keyset; + var keyset = this.querySelector(keysetId); + keyset.nextKeyset = this.dblTimer_.nextKeyset; clearTimeout(this.dblTimer_); + + this.classList.add('caps-locked'); + this.dblDetail_ = null; } } @@ -347,7 +413,6 @@ swipeInProgress = false; swipeStatus.resetAll(); } - // Remove the pointermove event hander here. this.removeEventListener('pointermove', this.swipeHandler, false); }, @@ -362,31 +427,48 @@ if (swipeInProgress) return; this.lastPressedKey.classList.remove('active'); - if (this.lastPressedKey != event.target) + if (this.lastPressedKey.char != event.target.char) return; if (repeatKey.key == event.target) { repeatKey.cancel(); return; } - var toKeyset = detail.toKeyset; - // Keyset transition key. - if (toKeyset) { - this.keyset = toKeyset; + var toKeysetId = detail.toKeyset; + // Keyset transition key. This is needed to transition from upper + // to lower case when we are not in caps mode. + if (toKeysetId) { + this.keyset = toKeysetId; this.querySelector('#' + this.layout + '-' + this.keyset).nextKeyset = detail.nextKeyset; } - var toLayout = detail.toLayout; + var toLayoutId = detail.toLayout; // Layout transition key. - if (toLayout) - this.layout = toLayout; + if (toLayoutId) + this.layout = toLayoutId; var char = detail.char; if (enterUpperOnSpace) { enterUpperOnSpace = false; - if (char == ' ') - this.keyset = 'upper'; + if (char == ' ') { + // If shift key defined in layout. + if(this.shift) { + var shiftDetail = this.shift.onSpaceAfterPunctuation(); + var toKeyset = shiftDetail.toKeyset; + // Check if transition defined. + if(toKeyset) { + this.keyset = toKeyset; + this.querySelector('#' + this.layout + '-' + + this.keyset).nextKeyset = shiftDetail.nextKeyset; + } + } else { + console.error('Capitalization on space after punctuation \ + enabled, but cannot find target keyset.'); + } + } } switch(char) { case 'Invalid': + swipeStatus.swipeFlags = 0; + return; case 'Shift': swipeStatus.swipeFlags = 0; return; @@ -401,7 +483,10 @@ default: break; } - insertText(char); + if (char.length == 1) + this.keyTyped(detail); + else + insertText(char); }, /* @@ -411,12 +496,17 @@ * @param {Object} detail The detail of pressed key. */ keyLongpress: function(event, detail) { + // If the gesture is long press, remove the pointermove listener. + this.removeEventListener('pointermove', this.swipeHandler, false); var toKeyset = detail.toKeyset; // Keyset transtion key. if (toKeyset) { this.keyset = toKeyset; this.querySelector('#' + this.layout + '-' + this.keyset).nextKeyset = detail.nextKeyset; + + // Locks the keyset before removing active to prevent flicker. + this.classList.add('caps-locked'); // Makes last pressed key inactive if transit to a new keyset on long // press. this.lastPressedKey.classList.remove('active'); @@ -424,7 +514,7 @@ }, /** - * Handles a change in the keyboard layout. Auto-selects the default + * Handles a change in the keyboard layout. Auto-selects the default * keyset for the new layout. */ layoutChanged: function() { @@ -435,14 +525,46 @@ keyboard.appendChild(flattenKeysets(keysets.content)); this.selectDefaultKeyset(); } else { - console.error('Unable to find layout ' + this.layout); - } + // Add link for the keysets if missing from the document. Force + // a layout change after resolving the import of the link. + var query = 'link[id=' + this.layout + ']'; + if (!document.querySelector(query)) { + // Layout has not beeen loaded yet. + var link = document.createElement('link'); + link.id = this.layout; + link.setAttribute('rel', 'import'); + link.setAttribute('href', 'layouts/' + this.layout + '.html'); + document.head.appendChild(link); + + // Load content for the new link element. + var self = this; + HTMLImports.importer.load(document, function() { + HTMLImports.parser.parseLink(link); + self.layoutChanged(); + }); + } + } } + this.classList.remove('caps-locked'); + this.shift = this.querySelector('kb-shift-key'); + if(this.shift) + this.shift.reset(); + }, + + /** + * Generates fabricated key events to simulate typing on a + * physical keyboard. + * @param {Object} detail Attributes of the key being typed. + */ + keyTyped: function(detail) { + var builder = this.$.keyCodeMetadata; + sendKeyEvent(builder.createVirtualKeyEvent(detail, "keydown")); + sendKeyEvent(builder.createVirtualKeyEvent(detail, "keyup")); }, /** * Selects the default keyset for a layout. - * @return {boolean} True if successful. This method can fail if the + * @return {boolean} True if successful. This method can fail if the * keysets corresponding to the layout have not been injected. */ selectDefaultKeyset: function() { @@ -452,10 +574,10 @@ var keysetsLoaded = false; for (var i = 0; i < keysets.length; i++) { var matches = keysets[i].id.match(regex); - if (matches && matches.length == 2) { + if (matches && matches.length == REGEX_MATCH_COUNT) { keysetsLoaded = true; if (keysets[i].isDefault) { - this.keyset = matches[1]; + this.keyset = matches[REGEX_KEYSET_INDEX]; return true; } } @@ -467,4 +589,3 @@ }); </script> </polymer-element> - diff --git a/chromium/ui/keyboard/resources/elements/kb-keyset.html b/chromium/ui/keyboard/resources/elements/kb-keyset.html index 365649d9830..92dd8b7f687 100644 --- a/chromium/ui/keyboard/resources/elements/kb-keyset.html +++ b/chromium/ui/keyboard/resources/elements/kb-keyset.html @@ -4,8 +4,9 @@ -- found in the LICENSE file. --> -<polymer-element name="kb-keyset" attributes="nextKeyset isDefault" - on-key-up="keyUp" on-key-longpress="keyLongpress"> +<polymer-element name="kb-keyset" attributes="nextKeyset isDefault + capsLocksTo capsLockable" on-key-up="keyUp" + on-key-longpress="keyLongpress"> <template> <style> @host { @@ -40,7 +41,7 @@ var altkeyMetadata = this.$.altkeyMetadata; var altkeys = altkeyMetadata.getAltkeys(detail.char, - !!detail.superscript); + !!detail.hintText); if (!altkeys) return; @@ -55,7 +56,7 @@ activeAltKeySet = altkeyMetadata.createAltkeySet(detail.char, maxLeftOffset, maxRightOffset, - detail.superscript); + detail.hintText); altkeyContainer.appendChild(activeAltKeySet); } diff --git a/chromium/ui/keyboard/resources/elements/kb-row.html b/chromium/ui/keyboard/resources/elements/kb-row.html index 0a00058a060..0398587daa2 100644 --- a/chromium/ui/keyboard/resources/elements/kb-row.html +++ b/chromium/ui/keyboard/resources/elements/kb-row.html @@ -12,8 +12,11 @@ -webkit-box-flex: 1; display: -webkit-box; text-align: center; - margin-right: 5px; - margin-top: 7px; + margin-right: 0.25em; + margin-top: 0.25em; + } + *:last-of-type { + margin-bottom: 0.25em; } } content::-webkit-distributed(kb-key) { diff --git a/chromium/ui/keyboard/resources/elements/kb-shift-key.html b/chromium/ui/keyboard/resources/elements/kb-shift-key.html new file mode 100644 index 00000000000..686a59c5125 --- /dev/null +++ b/chromium/ui/keyboard/resources/elements/kb-shift-key.html @@ -0,0 +1,186 @@ +<!-- + -- 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. + --> + +<polymer-element name="kb-shift-key" + attributes="lowerCaseKeysetId upperCaseKeysetId" + class="shift dark" char="Shift" extends="kb-key"> + <script> + (function () { + + /** + * The possible states of the shift key. + * Unlocked is the default state. Locked for capslocked, pressed is a + * key-down and tapped for a key-down followed by an immediate key-up. + * @const + * @type {Enum} + */ + var KEY_STATES = { + PRESSED: "pressed", // Key-down on shift key. + LOCKED: "locked", // Key is capslocked. + UNLOCKED: "unlocked", // Default state. + TAPPED: "tapped" // Key-down followed by key-up. + }; + + /** + * Uses a closure to define one long press timer among all shift keys + * regardless of the layout they are in. + * @type {function} + */ + var shiftLongPressTimer = undefined; + + /** + * The current state of the shift key. + * @type {Enum} + */ + var state = KEY_STATES.UNLOCKED; + + Polymer('kb-shift-key', { + /** + * Defines how capslock effects keyset transition. We always transition + * from the lowerCaseKeysetId to the upperCaseKeysetId if capslock is on. + * @type {string} + */ + lowerCaseKeysetId: 'lower', + upperCaseKeysetId: 'upper', + + up: function(event) { + if (state == KEY_STATES.PRESSED) { + state = KEY_STATES.TAPPED; + // TODO(rsadam@): Add chording logic here. + } + this.super(); + }, + + down: function(event) { + // First transition state so that populateDetails generates + // correct data. + switch (state) { + case KEY_STATES.UNLOCKED: + state = KEY_STATES.PRESSED; + break; + case KEY_STATES.TAPPED: + case KEY_STATES.LOCKED: + state = KEY_STATES.UNLOCKED; + break; + case KEY_STATES.PRESSED: + // We pressed another shift key at the same time, + // so ignore second press. + break; + default: + console.error("Undefined shift key state: " + state); + break; + } + // Trigger parent behaviour. + this.super(); + this.fire('enable-sel'); + // Populate double click transition details. + var detail = {}; + detail.char = this.char || this.textContent; + detail.toKeyset = this.upperCaseKeysetId; + detail.nextKeyset = undefined; + detail.callback = this.onDoubleClick; + this.fire('enable-dbl', detail); + }, + + generateLongPressTimer: function() { + return this.asyncMethod(function() { + var detail = this.populateDetails(); + if (state == KEY_STATES.LOCKED) { + // We don't care about the longpress if we are already + // capitalized. + return; + } else { + state = KEY_STATES.LOCKED; + detail.toKeyset = this.upperCaseKeysetId; + detail.nextKeyset = undefined; + } + this.fire('key-longpress', detail); + }, null, LONGPRESS_DELAY_MSEC); + }, + + /** + * Callback function for when a double click is triggered. + */ + onDoubleClick: function() { + state = KEY_STATES.LOCKED; + }, + + /** + * Notifies shift key that a non-control key was pressed down. + * A control key is defined as one of shift, control or alt. + */ + onNonControlKeyDown: function() { + // TODO(rsadam@): add logic for chording here. + switch (state) { + case (KEY_STATES.TAPPED): + state = KEY_STATES.UNLOCKED; + break; + case (KEY_STATES.PRESSED): + // Enter chording mode. First disable longpress timer. + clearTimeout(this.shiftLongPressTimer); + break; + default: + break; + } + }, + + /** + * Callback function for when a space is pressed after punctuation. + * @return {Object} The keyset transitions the keyboard should make. + */ + onSpaceAfterPunctuation: function() { + var detail = {}; + detail.toKeyset = this.upperCaseKeysetId; + detail.nextKeyset = this.lowerCaseKeysetId; + state = KEY_STATES.TAPPED; + return detail; + }, + + populateDetails: function() { + var detail = this.super(); + switch(state) { + case(KEY_STATES.LOCKED): + detail.toKeyset = this.upperCaseKeysetId; + break; + case(KEY_STATES.UNLOCKED): + detail.toKeyset = this.lowerCaseKeysetId; + break; + case(KEY_STATES.PRESSED): + detail.toKeyset = this.upperCaseKeysetId; + break; + case(KEY_STATES.TAPPED): + detail.toKeyset = this.upperCaseKeysetId; + detail.nextKeyset = this.lowerCaseKeysetId; + break; + } + return detail; + }, + + /** + * Resets the shift key state. + */ + reset: function() { + state = KEY_STATES.UNLOCKED; + }, + + /** + * Overrides longPressTimer for the shift key. + */ + get longPressTimer() { + return shiftLongPressTimer; + }, + + set longPressTimer(timer) { + shiftLongPressTimer = timer; + }, + + get state() { + return state; + } + }); + })(); + </script> +</polymer-element>
\ No newline at end of file diff --git a/chromium/ui/keyboard/resources/index.html b/chromium/ui/keyboard/resources/index.html index ac2982b4bc0..c18e8e89285 100644 --- a/chromium/ui/keyboard/resources/index.html +++ b/chromium/ui/keyboard/resources/index.html @@ -23,20 +23,22 @@ <link rel="import" href="elements/kb-altkey.html"> <link rel="import" href="elements/kb-altkey-data.html"> <link rel="import" href="elements/kb-altkey-set.html"> - + <link rel="import" href="elements/kb-key-codes.html"> <link rel="import" href="elements/kb-key-base.html"> <link rel="import" href="elements/kb-key.html"> <link rel="import" href="elements/kb-keyboard.html"> <link rel="import" href="elements/kb-keyset.html"> <link rel="import" href="elements/kb-row.html"> - <!-- TODO(kevers|biao): Switch to dynamic loading strategy once supported - in Polymer (http://www.crbug.com/260278).--> - <link id="dvorak" rel="import" href="layouts/dvorak.html"> - <link id="qwerty" rel="import" href="layouts/qwerty.html"> - <!--TODO(stevet): Import 'Open Sans' font. --> + <link rel="import" href="elements/kb-shift-key.html"> + <link rel="import" href="elements/kb-key-sequence.html"> + <link rel="import" href="elements/kb-key-import.html"> + <!-- New layouts are dynamically loaded on demand. The link elements are + -- inserted here. + --> </head> <body> - <kb-keyboard id="keyboard" touch-action="none" layout="qwerty"> + <!-- TODO(bshe): initial input type should not be hard coded to text. --> + <kb-keyboard id="keyboard" touch-action="none" inputType="text"> </kb-keyboard> </body> </html> diff --git a/chromium/ui/keyboard/resources/layouts/dvorak.html b/chromium/ui/keyboard/resources/layouts/dvorak.html index 2f90470a8d1..1bd2300aefd 100644 --- a/chromium/ui/keyboard/resources/layouts/dvorak.html +++ b/chromium/ui/keyboard/resources/layouts/dvorak.html @@ -4,15 +4,13 @@ -- found in the LICENSE file. --> -<link rel="import" href="../elements/kb-key-sequence.html"> -<link rel="import" href="../elements/kb-key-import.html"> <link id="spacebar-row" rel="import" href="spacebar-row.html"> <template> <kb-keyset id="dvorak-upper"> <kb-row> <kb-key class="tab dark" char="	" align="left">tab</kb-key> - <kb-key-sequence keys="",.PYFGCRL" superscripts="1234567890"></kb-key-sequence> + <kb-key-sequence keys="",.PYFGCRL" hintTexts="1234567890"></kb-key-sequence> <kb-key class="backspace dark" char="" repeat align="right">backspace</kb-key> </kb-row> <kb-row> @@ -21,14 +19,14 @@ <kb-key class='return dark' char="
" align="right">enter</kb-key> </kb-row> <kb-row> - <kb-shift-key toKeyset="up:lower" weight="1.8" align="left">shift</kb-shift-key> + <kb-shift-key weight="1.8" align="left">shift</kb-shift-key> <kb-key-sequence keys=";QJKXBMWVZ"></kb-key-sequence> - <kb-shift-key toKeyset="up:lower" weight="1.8" align="right">shift</kb-shift-key> + <kb-shift-key weight="1.8" align="right">shift</kb-shift-key> </kb-row> <kb-row> - <kb-key class="symbol dark" toKeyset="up:symbol" char="Invalid" align="left">#123</kb-key> + <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid" align="left">#123</kb-key> <kb-key-import importId="spacebar-row"></kb-key-import> - <kb-key class="symbol dark" toKeyset="up:symbol" char="Invalid" align="right">#123</kb-key> + <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid" align="right">#123</kb-key> <kb-layout-selector></kb-layout-selector> </kb-row> <kb-altkey-container hidden> @@ -38,7 +36,7 @@ <kb-keyset id="dvorak-lower" isDefault=true> <kb-row> <kb-key class="tab dark" char="	" align="left">tab</kb-key> - <kb-key-sequence keys="",.pyfgcrl" superscripts="1234567890"></kb-key-sequence> + <kb-key-sequence keys="",.pyfgcrl" hintTexts="1234567890"></kb-key-sequence> <kb-key class="backspace dark" char="" repeat align="right">backspace</kb-key> </kb-row> <kb-row> @@ -47,14 +45,14 @@ <kb-key class='return dark' char="
" align="right">enter</kb-key> </kb-row> <kb-row> - <kb-shift-key toKeyset="up:upper:lower; long:upper; dbl:upper" weight="1.8" align="left">shift</kb-shift-key> + <kb-shift-key weight="1.8" align="left">shift</kb-shift-key> <kb-key-sequence keys=";qjkxbmwvz"></kb-key-sequence> - <kb-shift-key toKeyset="up:upper:lower; long:upper; dbl:upper" weight="1.8" align="right">shift</kb-shift-key> + <kb-shift-key weight="1.8" align="right">shift</kb-shift-key> </kb-row> <kb-row> - <kb-key class="symbol dark" toKeyset="up:symbol" char="Invalid" align="left">#123</kb-key> + <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid" align="left">#123</kb-key> <kb-key-import importId="spacebar-row"></kb-key-import> - <kb-key class="symbol dark" toKeyset="up:symbol" char="Invalid" align="right">#123</kb-key> + <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid" align="right">#123</kb-key> <kb-layout-selector></kb-layout-selector> </kb-row> <kb-altkey-container hidden> @@ -73,14 +71,14 @@ <kb-key class='return dark' char="
" align="right">enter</kb-key> </kb-row> <kb-row> - <kb-key class="left-more dark" toKeyset="up:more" char="Invalid" align="left">more</kb-key> + <kb-key class="left-more dark" toKeyset="down:more" char="Invalid" align="left">more</kb-key> <kb-key-sequence keys="!"':;/?"></kb-key-sequence> - <kb-key class="right-more dark" toKeyset="up:more" char="Invalid" align="right">more</kb-key> + <kb-key class="right-more dark" toKeyset="down:more" char="Invalid" align="right">more</kb-key> </kb-row> <kb-row> - <kb-key class="symbol dark" toKeyset="up:lower" char="Invalid" align="left">abc</kb-key> + <kb-key class="symbol dark" toKeyset="down:lower" char="Invalid" align="left">abc</kb-key> <kb-key-import importId="spacebar-row"></kb-key-import> - <kb-key class="symbol dark" toKeyset="up:lower" char="Invalid" align="right">abc</kb-key> + <kb-key class="symbol dark" toKeyset="down:lower" char="Invalid" align="right">abc</kb-key> <kb-layout-selector></kb-layout-selector> </kb-row> <kb-altkey-container hidden> @@ -103,16 +101,16 @@ <kb-key class='return dark' char="
" align="right">enter</kb-key> </kb-row> <kb-row> - <kb-key class="left-more dark" toKeyset="up:symbol" char="Invalid" align="left">#123</kb-key> + <kb-key class="left-more dark" toKeyset="down:symbol" char="Invalid" align="left">#123</kb-key> <kb-key>×</kb-key><kb-key>÷</kb-key><kb-key>_</kb-key><kb-key>§</kb-key> <kb-key>¶</kb-key><kb-key>¡</kb-key><kb-key>¿</kb-key><kb-key>•</kb-key> <kb-key>Δ</kb-key> - <kb-key class="right-more dark" toKeyset="up:symbol" char="Invalid" align="right">#123</kb-key> + <kb-key class="right-more dark" toKeyset="down:symbol" char="Invalid" align="right">#123</kb-key> </kb-row> <kb-row> - <kb-key class="symbol dark" toKeyset="up:lower" char="Invalid" align="left">abc</kb-key> + <kb-key class="symbol dark" toKeyset="down:lower" char="Invalid" align="left">abc</kb-key> <kb-key-import importId="spacebar-row"></kb-key-import> - <kb-key class="symbol dark" toKeyset="up:lower" char="Invalid" align="right">abc</kb-key> + <kb-key class="symbol dark" toKeyset="down:lower" char="Invalid" align="right">abc</kb-key> <kb-layout-selector></kb-layout-selector> </kb-row> </kb-keyset> diff --git a/chromium/ui/keyboard/resources/layouts/numeric.html b/chromium/ui/keyboard/resources/layouts/numeric.html new file mode 100644 index 00000000000..6375f734a5f --- /dev/null +++ b/chromium/ui/keyboard/resources/layouts/numeric.html @@ -0,0 +1,28 @@ +<!-- + -- 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. + --> + +<template> + <kb-keyset id="numeric-symbol" isDefault=true> + <kb-row> + <kb-key>1</kb-key><kb-key>2</kb-key><kb-key>3</kb-key> + <kb-key class="dark">-</kb-key> + </kb-row> + <kb-row> + <kb-key>4</kb-key><kb-key>5</kb-key><kb-key>6</kb-key> + <kb-key class="dark">,</kb-key> + </kb-row> + <kb-row> + <kb-key>7</kb-key><kb-key>8</kb-key><kb-key>9</kb-key> + <kb-key char="" repeat class="dark">backspace</kb-key> + </kb-row> + <kb-row> + <kb-key char=" " class="dark">space</kb-key> + <kb-key>0</kb-key> + <kb-key class="dark">.</kb-key> + <kb-key char="	" class="dark">next</kb-key> + </kb-row> + </kb-keyset> +</template> diff --git a/chromium/ui/keyboard/resources/layouts/qwerty.html b/chromium/ui/keyboard/resources/layouts/qwerty.html index 0f19ebf80f3..361eaf0e726 100644 --- a/chromium/ui/keyboard/resources/layouts/qwerty.html +++ b/chromium/ui/keyboard/resources/layouts/qwerty.html @@ -4,15 +4,13 @@ -- found in the LICENSE file. --> -<link rel="import" href="../elements/kb-key-sequence.html"> -<link rel="import" href="../elements/kb-key-import.html"> <link id="spacebar-row" rel="import" href="spacebar-row.html"> <template> <kb-keyset id="qwerty-upper"> <kb-row> <kb-key class="tab dark" char="	" align="left">tab</kb-key> - <kb-key-sequence keys="QWERTYUIOP" superscripts="1234567890"></kb-key-sequence> + <kb-key-sequence keys="QWERTYUIOP" hintTexts="1234567890"></kb-key-sequence> <kb-key class="backspace dark" char="" repeat align="right">backspace</kb-key> </kb-row> <kb-row> @@ -21,17 +19,17 @@ <kb-key class='return dark' char="
" align="right">enter</kb-key> </kb-row> <kb-row> - <kb-shift-key toKeyset="up:lower" weight="1.8" align="left">shift</kb-shift-key> + <kb-shift-key weight="1.8" align="left">shift</kb-shift-key> <kb-key-sequence keys="ZXCVBNM"></kb-key-sequence> - <kb-key invert superscript="!" char="!">,</kb-key> - <kb-key invert superscript="?" char="?">.</kb-key> - <kb-shift-key toKeyset="up:lower" weight="1.8" align="right">shift</kb-shift-key> + <kb-key invert hintText="!" char="!">,</kb-key> + <kb-key invert hintText="?" char="?">.</kb-key> + <kb-shift-key weight="1.8" align="right">shift</kb-shift-key> </kb-row> <kb-row> - <kb-key class="symbol dark" toKeyset="up:symbol" char="Invalid" align="left">#123</kb-key> + <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid" align="left">#123</kb-key> <kb-key-import importId="spacebar-row"></kb-key-import> - <kb-key class="symbol dark" toKeyset="up:symbol" char="Invalid" align="right">#123</kb-key> - <kb-layout-selector toLayout="dvorak"></kb-layout-selector> + <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid" align="right">#123</kb-key> + <kb-hide-keyboard-key></kb-hide-keyboard-key> </kb-row> <kb-altkey-container hidden> </kb-altkey-container> @@ -40,7 +38,7 @@ <kb-keyset id="qwerty-lower" isDefault=true> <kb-row> <kb-key class="tab dark" char="	" align="left">tab</kb-key> - <kb-key-sequence keys="qwertyuiop" superscripts="1234567890"></kb-key-sequence> + <kb-key-sequence keys="qwertyuiop" hintTexts="1234567890"></kb-key-sequence> <kb-key class="backspace dark" char="" repeat align="right">backspace</kb-key> </kb-row> <kb-row> @@ -49,16 +47,16 @@ <kb-key class='return dark' char="
" align="right">enter</kb-key> </kb-row> <kb-row> - <kb-shift-key toKeyset="up:upper:lower; long:upper; dbl:upper" weight="1.8" align="left">shift</kb-shift-key> + <kb-shift-key weight="1.8" align="left">shift</kb-shift-key> <kb-key-sequence keys="zxcvbnm"></kb-key-sequence> - <kb-key superscript="!">,</kb-key><kb-key superscript="?">.</kb-key> - <kb-shift-key toKeyset="up:upper:lower; long:upper; dbl:upper" weight="1.8" align="right">shift</kb-shift-key> + <kb-key hintText="!">,</kb-key><kb-key hintText="?">.</kb-key> + <kb-shift-key weight="1.8" align="right">shift</kb-shift-key> </kb-row> <kb-row> - <kb-key class="symbol dark" toKeyset="up:symbol" char="Invalid" align="left">#123</kb-key> + <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid" align="left">#123</kb-key> <kb-key-import importId="spacebar-row"></kb-key-import> - <kb-key class="symbol dark" toKeyset="up:symbol" char="Invalid" align="right">#123</kb-key> - <kb-layout-selector toLayout="dvorak"></kb-layout-selector> + <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid" align="right">#123</kb-key> + <kb-hide-keyboard-key></kb-hide-keyboard-key> </kb-row> <kb-altkey-container hidden> </kb-altkey-container> @@ -82,17 +80,17 @@ <kb-key class='return dark' char="
" align="right">enter</kb-key> </kb-row> <kb-row> - <kb-key class="left-more dark" toKeyset="up:more" char="Invalid" align="left">more</kb-key> + <kb-key class="left-more dark" toKeyset="down:more" char="Invalid" align="left">more</kb-key> <kb-key>:</kb-key><kb-key>;</kb-key><kb-key>-</kb-key><kb-key>'</kb-key> <kb-key>"</kb-key><kb-key>!</kb-key> <kb-key>?</kb-key><kb-key>,</kb-key><kb-key>.</kb-key> - <kb-key class="right-more dark" toKeyset="up:more" char="Invalid" align="right">more</kb-key> + <kb-key class="right-more dark" toKeyset="down:more" char="Invalid" align="right">more</kb-key> </kb-row> <kb-row> - <kb-key class="symbol dark" toKeyset="up:lower" char="Invalid" align="left">abc</kb-key> + <kb-key class="symbol dark" toKeyset="down:lower" char="Invalid" align="left">abc</kb-key> <kb-key-import importId="spacebar-row"></kb-key-import> - <kb-key class="symbol dark" toKeyset="up:lower" char="Invalid" align="right">abc</kb-key> - <kb-layout-selector toLayout="dvorak"></kb-layout-selector> + <kb-key class="symbol dark" toKeyset="down:lower" char="Invalid" align="right">abc</kb-key> + <kb-hide-keyboard-key></kb-hide-keyboard-key> </kb-row> <kb-altkey-container hidden> </kb-altkey-container> @@ -114,17 +112,17 @@ <kb-key class='return dark' char="
" align="right">enter</kb-key> </kb-row> <kb-row> - <kb-key class="left-more dark" toKeyset="up:symbol" char="Invalid" align="left">#123</kb-key> + <kb-key class="left-more dark" toKeyset="down:symbol" char="Invalid" align="left">#123</kb-key> <kb-key>×</kb-key><kb-key>÷</kb-key><kb-key>_</kb-key><kb-key>§</kb-key> <kb-key>¶</kb-key><kb-key>¡</kb-key><kb-key>¿</kb-key><kb-key>•</kb-key> <kb-key>Δ</kb-key> - <kb-key class="right-more dark" toKeyset="up:symbol" char="Invalid" align="right">#123</kb-key> + <kb-key class="right-more dark" toKeyset="down:symbol" char="Invalid" align="right">#123</kb-key> </kb-row> <kb-row> - <kb-key class="symbol dark" toKeyset="up:lower" char="Invalid" align="left">abc</kb-key> + <kb-key class="symbol dark" toKeyset="down:lower" char="Invalid" align="left">abc</kb-key> <kb-key-import importId="spacebar-row"></kb-key-import> - <kb-key class="symbol dark" toKeyset="up:lower" char="Invalid" align="right">abc</kb-key> - <kb-layout-selector toLayout="dvorak"></kb-layout-selector> + <kb-key class="symbol dark" toKeyset="down:lower" char="Invalid" align="right">abc</kb-key> + <kb-hide-keyboard-key></kb-hide-keyboard-key> </kb-row> </kb-keyset> </template> diff --git a/chromium/ui/keyboard/resources/layouts/symbol-altkeys.js b/chromium/ui/keyboard/resources/layouts/symbol-altkeys.js index 24dfed8757a..a123dbf2a5d 100644 --- a/chromium/ui/keyboard/resources/layouts/symbol-altkeys.js +++ b/chromium/ui/keyboard/resources/layouts/symbol-altkeys.js @@ -3,21 +3,21 @@ // found in the LICENSE file. var symbolAltKeys = { - '1': ['\u00B9', // Superscript 1 + '1': ['\u00B9', // HintText 1 '\u00BD', // Vulgar fraction 1/2 '\u2153', // Vulgar fraction 1/3 '\u00BC', // Vulgar fraction 1/4 '\u215B'], // Vulgar fraction 1/8 - '2': ['\u00B2', // Superscript 2 + '2': ['\u00B2', // HintText 2 '\u2154'], // Vulgar fraction 2/3 - '3': ['\u00B3', // Superscript 3 + '3': ['\u00B3', // HintText 3 '\u00BE', // Vulgar fraction 3/4 '\u215C'], // Vulgar fraction 3/8 - '4': ['\u2074'], // Superscript 4 + '4': ['\u2074'], // HintText 4 '5': ['\u215D'], // Vulgar fraction 5/8 '7': ['\u215E'], // Vulgar fraction 7/8 '0': ['\u00D8', // Empty set - '\u207F'], // Superscript small n + '\u207F'], // HintText small n '$': ['\u20AC', // Euro sign '\u00A5', // Yen sign '\u00A3', // Pound sign @@ -36,7 +36,8 @@ var symbolAltKeys = { '!': ['\u00A1'], // Inverted exclamation mark '?': ['\u00BF'], // Inverted question mark '(': ['<', '{', '['], - ')': ['>', '}', ']'] + ')': ['>', '}', ']'], + '.com' : ['.net','.org','.gov'] }; document.addEventListener('WebComponentsReady', function() { diff --git a/chromium/ui/keyboard/resources/layouts/webui_qwerty.html b/chromium/ui/keyboard/resources/layouts/webui_qwerty.html index 9abd2e67c86..0c5353f810f 100644 --- a/chromium/ui/keyboard/resources/layouts/webui_qwerty.html +++ b/chromium/ui/keyboard/resources/layouts/webui_qwerty.html @@ -19,13 +19,13 @@ <div class="half-key-spacer"></div> </kb-row> <kb-row> - <kb-shift-key class="padded-left-special" toKeyset="up:lower" weight="1.4">shift</kb-shift-key> + <kb-shift-key class="padded-left-special" weight="1.4">shift</kb-shift-key> <kb-key>Z</kb-key><kb-key>X</kb-key><kb-key>C</kb-key><kb-key>V</kb-key> <kb-key>B</kb-key><kb-key>N</kb-key><kb-key>M</kb-key> <kb-key class="backspace padded-right-special dark" char="" repeat>delete</kb-key> </kb-row> <kb-row> - <kb-key class="symbol dark" toKeyset="up:symbol" char="Invalid">?123</kb-key> + <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid">?123</kb-key> <kb-key class="microphone dark" char="Microphone"></kb-key> <kb-key class="dark">,</kb-key> <kb-key class="space dark" char=" "></kb-key> @@ -50,13 +50,13 @@ <div class="half-key-spacer"></div> </kb-row> <kb-row> - <kb-shift-key class="padded-left-special" toKeyset="up:upper:lower; long:upper; dbl:upper" weight="1.4">shift</kb-shift-key> + <kb-shift-key class="padded-left-special" weight="1.4">shift</kb-shift-key> <kb-key>z</kb-key><kb-key>x</kb-key><kb-key>c</kb-key><kb-key>v</kb-key> <kb-key>b</kb-key><kb-key>n</kb-key><kb-key>m</kb-key> <kb-key class="backspace padded-right-special dark" char="" repeat>delete</kb-key> </kb-row> <kb-row> - <kb-key class="symbol dark" toKeyset="up:symbol" char="Invalid">?123</kb-key> + <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid">?123</kb-key> <kb-key class="microphone dark" char="Microphone"></kb-key> <kb-key class="dark">,</kb-key> <kb-key class="space dark" char=" "></kb-key> @@ -78,13 +78,13 @@ <kb-key>/</kb-key><kb-key>(</kb-key><kb-key>)</kb-key> </kb-row> <kb-row> - <kb-key class="left-more padded-left-special dark" toKeyset="up:more" char="Invalid">more</kb-key> + <kb-key class="left-more padded-left-special dark" toKeyset="down:more" char="Invalid">more</kb-key> <kb-key>"</kb-key><kb-key>'</kb-key><kb-key>-</kb-key> <kb-key>+</kb-key><kb-key>!</kb-key><kb-key>?</kb-key> <kb-key class="backspace padded-right-special dark" char="" repeat>delete</kb-key> </kb-row> <kb-row> - <kb-key class="symbol dark" toKeyset="up:lower" char="Invalid">abc</kb-key> + <kb-key class="symbol dark" toKeyset="down:lower" char="Invalid">abc</kb-key> <kb-key class="microphone dark" char="Microphone"></kb-key> <kb-key class="dark">,</kb-key> <kb-key class="space dark" char=" "></kb-key> @@ -105,13 +105,13 @@ <kb-key>\</kb-key><kb-key><</kb-key><kb-key>></kb-key> </kb-row> <kb-row> - <kb-key class="left-more padded-left-special dark" toKeyset="up:symbol" char="Invalid">?123</kb-key> + <kb-key class="left-more padded-left-special dark" toKeyset="down:symbol" char="Invalid">?123</kb-key> <kb-key>`</kb-key><kb-key>~</kb-key><kb-key>_</kb-key><kb-key>=</kb-key> <kb-key>[</kb-key><kb-key>]</kb-key> <kb-key class="backspace padded-right-special dark" char="" repeat>delete</kb-key> </kb-row> <kb-row> - <kb-key class="symbol dark" toKeyset="up:lower" char="Invalid">abc</kb-key> + <kb-key class="symbol dark" toKeyset="down:lower" char="Invalid">abc</kb-key> <kb-key class="microphone dark" char="Microphone"></kb-key> <kb-key class="dark">,</kb-key> <kb-key class="space dark" char=" "></kb-key> diff --git a/chromium/ui/keyboard/resources/main.css b/chromium/ui/keyboard/resources/main.css index 149384f8e67..b0948afd95c 100644 --- a/chromium/ui/keyboard/resources/main.css +++ b/chromium/ui/keyboard/resources/main.css @@ -22,6 +22,7 @@ kb-keyboard { } kb-shift-key, +kb-hide-keyboard-key, kb-layout-selector, kb-key { background-color: #3b3b3e; @@ -32,9 +33,9 @@ kb-key { border-radius: 2px; color: #ffffff; display: -webkit-box; - font-family: 'Open Sans', sans-serif; + font-family: 'Open Sans', 'Noto Sans UI', sans-serif; font-weight: 300; - margin-left: 7px; + margin-left: 0.25em; position: relative; } @@ -45,14 +46,14 @@ kb-key::x-key { height: 1.2em; left: 0; margin: auto; - padding-left: 10px; - padding-right: 10px; + padding-left: 0.7em; + padding-right: 0.7em; position: absolute; right: 0; top: 0; } -kb-key::x-superscript { +kb-key::x-hinttext { color: #7c7c7c; font-size: 70%; position: absolute; @@ -64,13 +65,19 @@ kb-key::x-key[inverted] { color: #7c7c7c; } -kb-key::x-superscript[inverted] { +kb-key::x-hinttext[inverted] { color: #ffffff; } -kb-shift-key.dark, -kb-layout-selector.dark, -kb-key.dark { +/** +* Controls whether the shift key should be highlighted or not. +* Only highlights if we are in the upper keyset, but not capslocked. +*/ +kb-keyboard:not(.caps-locked)[keyset=upper] kb-shift-key { + color: lightblue; +} + +*.dark { background-color: #2a2a2c; border-top: 2px solid #3a3a3c; } @@ -87,6 +94,7 @@ kb-altkey::x-key { text-align: center; } +.caps-locked kb-shift-key, .active { background-color: #848490 !important; border-top: 2px solid #A9A9AF !important; @@ -137,25 +145,29 @@ kb-altkey::x-key { -webkit-box-flex: 0.6 !important; } -.backspace, -.dotcom, -.left-more, -.shift, -.return, -.right-more, -.symbol, -.tab { +kb-shift-key.shift, +kb-key:-webkit-any(.backspace, + .dotcom, + .left-more, + .return, + .symbol, + .tab) { font-size: 70%; + /* Adjust margin for consistent spacing with the smaller font size. */ + margin-left: 0.35em; } .microphone { background-image: url('images/microphone.svg'); + background-position: 4%; + background-size: 25%; } .audio .microphone { background-image: url('images/microphone-green.svg'); } +.hide-keyboard, .layout-selector { background-image: url('images/keyboard.svg'); } diff --git a/chromium/ui/keyboard/resources/manifest.json b/chromium/ui/keyboard/resources/manifest.json index 93d4a8fab52..5cd326c28a1 100644 --- a/chromium/ui/keyboard/resources/manifest.json +++ b/chromium/ui/keyboard/resources/manifest.json @@ -10,7 +10,7 @@ }, "permissions": [ "audioCapture", - "experimental" + "virtualKeyboardPrivate" ], "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'" } diff --git a/chromium/ui/keyboard/resources/webui/api_adapter.js b/chromium/ui/keyboard/resources/webui/api_adapter.js index 1d24ba68bc2..17d84b9d7c3 100644 --- a/chromium/ui/keyboard/resources/webui/api_adapter.js +++ b/chromium/ui/keyboard/resources/webui/api_adapter.js @@ -5,3 +5,78 @@ function insertText(text) { chrome.send('insertText', [ text ]); } + +function sendKeyEvent(event) { + chrome.send('sendKeyEvent', [ event ]); +} + +function hideKeyboard() { + chrome.send('hideKeyboard'); +} + +(function(exports) { + /** + * An array to save callbacks of each request. + * @type {Array.<function(Object)>} + */ + var requestIdCallbackMap = []; + + /** + * An incremental integer that represents a unique requestId. + * @type {number} + */ + var requestId = 0; + + /** + * Called when a text input box gets focus. + * @param {object} inputContext Describes an input context. It only contains + * the type of text input box at present and only "password", "number" and + * "text" are supported. + */ + function OnTextInputBoxFocused(inputContext) { + keyboard.inputType = inputContext.type; + } + + /** + * Gets the context of the focused input field. The context is returned as a + * paramter in the |callback|. + * @param {function(Object)} callback The callback function after the webui + * function finished. + * @return {number} The ID of the new request. + */ + function GetInputContext(callback) { + var id = requestId; + requestIdCallbackMap[id] = callback; + chrome.send('getInputContext', [ id ]); + requestId++; + return id; + } + + /** + * Cancel the callback specified by requestId. + * @param {number} requestId The requestId of the callback that about to + * cancel. + */ + function CancelRequest(requestId) { + requestIdCallbackMap[requestId] = undefined; + } + + /** + * Webui function callback. Any call to chrome.send('getInputContext', [id]) + * should trigger this function being called with the parameter + * inputContext.requestId == id. + * @param {Object} inputContext The context of focused input field. Note we + * only have type(input box type) and requestId fields now. + */ + function GetInputContextCallback(inputContext) { + var requestId = inputContext.requestId; + if (!requestIdCallbackMap[requestId]) + return; + requestIdCallbackMap[requestId](inputContext); + } + + exports.OnTextInputBoxFocused = OnTextInputBoxFocused; + exports.getInputContext = GetInputContext; + exports.cancelRequest = CancelRequest; + exports.GetInputContextCallback = GetInputContextCallback; +})(this); diff --git a/chromium/ui/keyboard/resources/webui/main.css b/chromium/ui/keyboard/resources/webui/main.css index 5217143c811..092abd26362 100644 --- a/chromium/ui/keyboard/resources/webui/main.css +++ b/chromium/ui/keyboard/resources/webui/main.css @@ -31,7 +31,7 @@ kb-key { display: -webkit-box; font-family: 'Open Sans', sans-serif; font-weight: 600; - margin-left: 3px; + margin-left: 0.2em; position: relative; } @@ -41,14 +41,14 @@ kb-key::x-key { height: 1.2em; left: 0; margin: auto; - padding-left: 10px; - padding-right: 10px; + padding-left: 0.5em; + padding-right: 0.5em; position: absolute; right: 0; top: 0; } -kb-key::x-superscript { +kb-key::x-hinttext { color: #7c7c7c; font-size: 70%; position: absolute; @@ -60,7 +60,7 @@ kb-key::x-key[inverted] { color: #7c7c7c; } -kb-key::x-superscript[inverted] { +kb-key::x-hinttext[inverted] { color: #ffffff; } diff --git a/chromium/ui/keyboard/resources/webui_index.html b/chromium/ui/keyboard/resources/webui_index.html index 48b1637571f..47ae8ed169b 100644 --- a/chromium/ui/keyboard/resources/webui_index.html +++ b/chromium/ui/keyboard/resources/webui_index.html @@ -25,11 +25,14 @@ <link rel="import" href="elements/kb-altkey-container.html"> <link rel="import" href="elements/kb-altkey-data.html"> <link rel="import" href="elements/kb-altkey-set.html"> + <link rel="import" href="elements/kb-key-codes.html"> <link rel="import" href="elements/kb-key-base.html"> <link rel="import" href="elements/kb-key.html"> <link rel="import" href="elements/kb-keyboard.html"> <link rel="import" href="elements/kb-keyset.html"> <link rel="import" href="elements/kb-row.html"> + <link rel="import" href="elements/kb-shift-key.html"> + <link id="numeric" rel="import" href="layouts/numeric.html"> <link id="qwerty" rel="import" href="layouts/qwerty.html"> <!--TODO(stevet): Import 'Open Sans' font. --> <script src="main.js"></script> diff --git a/chromium/ui/linux_ui/linux_ui_export.h b/chromium/ui/linux_ui/linux_ui_export.h deleted file mode 100644 index 68f2ab544ab..00000000000 --- a/chromium/ui/linux_ui/linux_ui_export.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2012 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. - -#ifndef UI_LINUX_UI_LINUX_UI_EXPORT_H_ -#define UI_LINUX_UI_LINUX_UI_EXPORT_H_ - -// Defines LINUX_UI_EXPORT so that functionality implemented by the -// native_theme library can be exported to consumers. - -#if defined(COMPONENT_BUILD) -#if defined(WIN32) - -#if defined(LINUX_UI_IMPLEMENTATION) -#define LINUX_UI_EXPORT __declspec(dllexport) -#else -#define LINUX_UI_EXPORT __declspec(dllimport) -#endif // defined(LINUX_UI_IMPLEMENTATION) - -#else // !defined(WIN32) - -#if defined(LINUX_UI_IMPLEMENTATION) -#define LINUX_UI_EXPORT __attribute__((visibility("default"))) -#else -#define LINUX_UI_EXPORT -#endif - -#endif // defined(WIN32) - -#else // !defined(COMPONENT_BUILD) - -#define LINUX_UI_EXPORT - -#endif // defined(COMPONENT_BUILD) - -#endif // UI_LINUX_UI_LINUX_UI_EXPORT_H_ diff --git a/chromium/ui/message_center/cocoa/notification_controller.h b/chromium/ui/message_center/cocoa/notification_controller.h index 41af2b23280..47f1e87b67d 100644 --- a/chromium/ui/message_center/cocoa/notification_controller.h +++ b/chromium/ui/message_center/cocoa/notification_controller.h @@ -41,13 +41,16 @@ MESSAGE_CENTER_EXPORT base::scoped_nsobject<NSImageView> icon_; // The title of the message. - base::scoped_nsobject<NSTextField> title_; + base::scoped_nsobject<NSTextView> title_; // Body text of the message. Hidden for list notifications. - base::scoped_nsobject<NSTextField> message_; + base::scoped_nsobject<NSTextView> message_; - // Container for optional list item views. - base::scoped_nsobject<NSView> listItemView_; + // Context-giving text of the message. Alternate font used to distinguish it. + base::scoped_nsobject<NSTextView> contextMessage_; + + // Container for optional list view that contains multiple items. + base::scoped_nsobject<NSView> listView_; // Container for optional progress bar view. base::scoped_nsobject<NSProgressIndicator> progressBarView_; diff --git a/chromium/ui/message_center/cocoa/notification_controller.mm b/chromium/ui/message_center/cocoa/notification_controller.mm index 965ba423f24..3237a72ca94 100644 --- a/chromium/ui/message_center/cocoa/notification_controller.mm +++ b/chromium/ui/message_center/cocoa/notification_controller.mm @@ -14,7 +14,7 @@ #import "ui/base/cocoa/hover_image_button.h" #include "ui/base/l10n/l10n_util_mac.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/base/text/text_elider.h" +#include "ui/gfx/text_elider.h" #include "ui/message_center/message_center.h" #include "ui/message_center/message_center_style.h" #include "ui/message_center/notification.h" @@ -150,6 +150,14 @@ [controller_ notificationClicked]; } +- (NSView*)hitTest:(NSPoint)point { + // Route the mouse click events on NSTextView to the container view. + NSView* hitView = [super hitTest:point]; + if (hitView) + return [hitView isKindOfClass:[NSTextView class]] ? self : hitView; + return nil; +} + - (BOOL)accessibilityIsIgnored { return NO; } @@ -181,12 +189,6 @@ //////////////////////////////////////////////////////////////////////////////// @interface MCNotificationController (Private) -// Returns a string with item's title in title color and item's message in -// message color. -+ (NSAttributedString*) - attributedStringForItem:(const message_center::NotificationItem&)item - font:(NSFont*)font; - // Configures a NSBox to be borderless, titleless, and otherwise appearance- // free. - (void)configureCustomBox:(NSBox*)box; @@ -203,20 +205,24 @@ // Initializes message_ in the given frame. - (void)configureBodyInFrame:(NSRect)rootFrame; -// Creates a NSTextField that the caller owns configured as a label in a +// Initializes contextMessage_ in the given frame. +- (void)configureContextMessageInFrame:(NSRect)rootFrame; + +// Creates a NSTextView that the caller owns configured as a label in a // notification. -- (NSTextField*)newLabelWithFrame:(NSRect)frame; +- (NSTextView*)newLabelWithFrame:(NSRect)frame; // Gets the rectangle in which notification content should be placed. This // rectangle is to the right of the icon and left of the control buttons. // This depends on the icon_ and closeButton_ being initialized. - (NSRect)currentContentRect; -// Returns the wrapped text that could fit within the given text field with not -// more than the given number of lines. The Ellipsis could be added at the end -// of the last line if it is too long. +// Returns the wrapped text that could fit within the content rect with not +// more than the given number of lines. The wrapped text would be painted using +// the given font. The Ellipsis could be added at the end of the last line if +// it is too long. - (string16)wrapText:(const string16&)text - forField:(NSTextField*)field + forFont:(NSFont*)font maxNumberOfLines:(size_t)lines; @end @@ -260,6 +266,10 @@ [self configureBodyInFrame:rootFrame]; [rootView addSubview:message_]; + // Create the context message body. + [self configureContextMessageInFrame:rootFrame]; + [rootView addSubview:contextMessage_]; + // Populate the data. [self updateNotification:notification_]; } @@ -285,48 +295,78 @@ CGFloat messageTopGap = roundf([[message_ font] ascender] - [[message_ font] capHeight]); + CGFloat messageBottomGap = roundf(fabs([[message_ font] descender])); CGFloat messagePadding = message_center::kTextTopPadding - titleBottomGap - messageTopGap; + CGFloat contextMessageTopGap = roundf( + [[contextMessage_ font] ascender] - [[contextMessage_ font] capHeight]); + CGFloat contextMessagePadding = + message_center::kTextTopPadding - messageBottomGap - contextMessageTopGap; + // Set the title and recalculate the frame. - [title_ setStringValue:base::SysUTF16ToNSString( + [title_ setString:base::SysUTF16ToNSString( [self wrapText:notification_->title() - forField:title_ + forFont:[title_ font] maxNumberOfLines:message_center::kTitleLineLimit])]; [title_ sizeToFit]; NSRect titleFrame = [title_ frame]; titleFrame.origin.y = NSMaxY(rootFrame) - titlePadding - NSHeight(titleFrame); // Set the message and recalculate the frame. - [message_ setStringValue:base::SysUTF16ToNSString( + [message_ setString:base::SysUTF16ToNSString( [self wrapText:notification_->message() - forField:title_ + forFont:[message_ font] maxNumberOfLines:message_center::kMessageExpandedLineLimit])]; - [message_ setHidden:NO]; [message_ sizeToFit]; NSRect messageFrame = [message_ frame]; - messageFrame.origin.y = - NSMinY(titleFrame) - messagePadding - NSHeight(messageFrame); - messageFrame.size.height = NSHeight([message_ frame]); - // Create the list item views (up to a maximum). - [listItemView_ removeFromSuperview]; + // If there are list items, then the message_ view should not be displayed. const std::vector<message_center::NotificationItem>& items = notification->items(); - NSRect listFrame = NSZeroRect; if (items.size() > 0) { - // If there are list items, then the message_ view should not be displayed. [message_ setHidden:YES]; messageFrame.origin.y = titleFrame.origin.y; messageFrame.size.height = 0; + } else { + [message_ setHidden:NO]; + messageFrame.origin.y = + NSMinY(titleFrame) - messagePadding - NSHeight(messageFrame); + messageFrame.size.height = NSHeight([message_ frame]); + } + // Set the context message and recalculate the frame. + [contextMessage_ setString:base::SysUTF16ToNSString( + [self wrapText:notification_->context_message() + forFont:[contextMessage_ font] + maxNumberOfLines:message_center::kContextMessageLineLimit])]; + [contextMessage_ sizeToFit]; + NSRect contextMessageFrame = [contextMessage_ frame]; + + if (notification_->context_message().empty()) { + [contextMessage_ setHidden:YES]; + contextMessageFrame.origin.y = messageFrame.origin.y; + contextMessageFrame.size.height = 0; + } else { + [contextMessage_ setHidden:NO]; + contextMessageFrame.origin.y = + NSMinY(messageFrame) - + contextMessagePadding - + NSHeight(contextMessageFrame); + contextMessageFrame.size.height = NSHeight([contextMessage_ frame]); + } + + // Create the list item views (up to a maximum). + [listView_ removeFromSuperview]; + NSRect listFrame = NSZeroRect; + if (items.size() > 0) { listFrame = [self currentContentRect]; listFrame.origin.y = 0; listFrame.size.height = 0; - listItemView_.reset([[NSView alloc] initWithFrame:listFrame]); - [listItemView_ accessibilitySetOverrideValue:NSAccessibilityListRole + listView_.reset([[NSView alloc] initWithFrame:listFrame]); + [listView_ accessibilitySetOverrideValue:NSAccessibilityListRole forAttribute:NSAccessibilityRoleAttribute]; - [listItemView_ + [listView_ accessibilitySetOverrideValue:NSAccessibilityContentListSubrole forAttribute:NSAccessibilitySubroleAttribute]; CGFloat y = 0; @@ -337,23 +377,50 @@ const int kNumNotifications = std::min(items.size(), message_center::kNotificationMaximumItems); for (int i = kNumNotifications - 1; i >= 0; --i) { - NSTextField* field = [self newLabelWithFrame: + NSTextView* itemView = [self newLabelWithFrame: NSMakeRect(0, y, NSWidth(listFrame), lineHeight)]; - [[field cell] setUsesSingleLineMode:YES]; - [field setAttributedStringValue: - [MCNotificationController attributedStringForItem:items[i] - font:font]]; - [listItemView_ addSubview:field]; + [itemView setFont:font]; + + // Disable the word-wrap in order to show the text in single line. + [[itemView textContainer] setContainerSize:NSMakeSize(FLT_MAX, FLT_MAX)]; + [[itemView textContainer] setWidthTracksTextView:NO]; + + // Construct the text from the title and message. + string16 text = + items[i].title + base::UTF8ToUTF16(" ") + items[i].message; + string16 ellidedText = + [self wrapText:text forFont:font maxNumberOfLines:1]; + [itemView setString:base::SysUTF16ToNSString(ellidedText)]; + + // Use dim color for the title part. + NSColor* titleColor = + gfx::SkColorToCalibratedNSColor(message_center::kRegularTextColor); + NSRange titleRange = NSMakeRange( + 0, + std::min(ellidedText.size(), items[i].title.size())); + [itemView setTextColor:titleColor range:titleRange]; + + // Use dim color for the message part if it has not been truncated. + if (ellidedText.size() > items[i].title.size() + 1) { + NSColor* messageColor = + gfx::SkColorToCalibratedNSColor(message_center::kDimTextColor); + NSRange messageRange = NSMakeRange( + items[i].title.size() + 1, + ellidedText.size() - items[i].title.size() - 1); + [itemView setTextColor:messageColor range:messageRange]; + } + + [listView_ addSubview:itemView]; y += lineHeight; } // TODO(thakis): The spacing is not completely right. CGFloat listTopPadding = - message_center::kTextTopPadding - messageTopGap; + message_center::kTextTopPadding - contextMessageTopGap; listFrame.size.height = y; listFrame.origin.y = - NSMinY(titleFrame) - listTopPadding - NSHeight(listFrame); - [listItemView_ setFrame:listFrame]; - [[self view] addSubview:listItemView_]; + NSMinY(contextMessageFrame) - listTopPadding - NSHeight(listFrame); + [listView_ setFrame:listFrame]; + [[self view] addSubview:listView_]; } // Create the progress bar view if needed. @@ -361,7 +428,7 @@ NSRect progressBarFrame = NSZeroRect; if (notification->type() == message_center::NOTIFICATION_TYPE_PROGRESS) { progressBarFrame = [self currentContentRect]; - progressBarFrame.origin.y = NSMinY(messageFrame) - + progressBarFrame.origin.y = NSMinY(contextMessageFrame) - message_center::kProgressBarTopPadding - message_center::kProgressBarThickness; progressBarFrame.size.height = message_center::kProgressBarThickness; @@ -376,8 +443,8 @@ // If the bottom-most element so far is out of the rootView's bounds, resize // the view. - CGFloat minY = NSMinY(messageFrame); - if (listItemView_ && NSMinY(listFrame) < minY) + CGFloat minY = NSMinY(contextMessageFrame); + if (listView_ && NSMinY(listFrame) < minY) minY = NSMinY(listFrame); if (progressBarView_ && NSMinY(progressBarFrame) < minY) minY = NSMinY(progressBarFrame); @@ -386,6 +453,7 @@ rootFrame.size.height += delta; titleFrame.origin.y += delta; messageFrame.origin.y += delta; + contextMessageFrame.origin.y += delta; listFrame.origin.y += delta; progressBarFrame.origin.y += delta; } @@ -456,6 +524,7 @@ rootFrame.size.height += NSHeight(frame); titleFrame.origin.y += NSHeight(frame); messageFrame.origin.y += NSHeight(frame); + contextMessageFrame.origin.y += NSHeight(frame); listFrame.origin.y += NSHeight(frame); progressBarFrame.origin.y += NSHeight(frame); @@ -467,6 +536,7 @@ rootFrame.size.height += bottomAdjust; titleFrame.origin.y += bottomAdjust; messageFrame.origin.y += bottomAdjust; + contextMessageFrame.origin.y += bottomAdjust; listFrame.origin.y += bottomAdjust; progressBarFrame.origin.y += bottomAdjust; } @@ -474,7 +544,8 @@ [[self view] setFrame:rootFrame]; [title_ setFrame:titleFrame]; [message_ setFrame:messageFrame]; - [listItemView_ setFrame:listFrame]; + [contextMessage_ setFrame:contextMessageFrame]; + [listView_ setFrame:listFrame]; [progressBarView_ setFrame:progressBarFrame]; return rootFrame; @@ -504,42 +575,6 @@ // Private ///////////////////////////////////////////////////////////////////// -+ (NSAttributedString*) - attributedStringForItem:(const message_center::NotificationItem&)item - font:(NSFont*)font { - NSString* text = base::SysUTF16ToNSString( - item.title + base::UTF8ToUTF16(" ") + item.message); - NSMutableAttributedString* formattedText = - [[[NSMutableAttributedString alloc] initWithString:text] autorelease]; - - base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle( - [[NSParagraphStyle defaultParagraphStyle] mutableCopy]); - [paragraphStyle setLineBreakMode:NSLineBreakByTruncatingTail]; - NSDictionary* sharedAttribs = @{ - NSFontAttributeName : font, - NSParagraphStyleAttributeName : paragraphStyle, - }; - const NSRange range = NSMakeRange(0, [formattedText length] - 1); - [formattedText addAttributes:sharedAttribs range:range]; - - NSDictionary* titleAttribs = @{ - NSForegroundColorAttributeName : - gfx::SkColorToCalibratedNSColor(message_center::kRegularTextColor), - }; - const NSRange titleRange = NSMakeRange(0, item.title.size()); - [formattedText addAttributes:titleAttribs range:titleRange]; - - NSDictionary* messageAttribs = @{ - NSForegroundColorAttributeName : - gfx::SkColorToCalibratedNSColor(message_center::kDimTextColor), - }; - const NSRange messageRange = - NSMakeRange(item.title.size() + 1, item.message.size()); - [formattedText addAttributes:messageAttribs range:messageRange]; - - return formattedText; -} - - (void)configureCustomBox:(NSBox*)box { [box setBoxType:NSBoxCustom]; [box setBorderType:NSNoBorder]; @@ -611,17 +646,29 @@ message_.reset([self newLabelWithFrame:frame]); [message_ setAutoresizingMask:NSViewMinYMargin]; [message_ setTextColor:gfx::SkColorToCalibratedNSColor( - message_center::kDimTextColor)]; + message_center::kRegularTextColor)]; [message_ setFont: [NSFont messageFontOfSize:message_center::kMessageFontSize]]; } -- (NSTextField*)newLabelWithFrame:(NSRect)frame { - NSTextField* label = [[NSTextField alloc] initWithFrame:frame]; +- (void)configureContextMessageInFrame:(NSRect)rootFrame { + NSRect frame = [self currentContentRect]; + frame.size.height = 0; + contextMessage_.reset([self newLabelWithFrame:frame]); + [contextMessage_ setAutoresizingMask:NSViewMinYMargin]; + [contextMessage_ setTextColor:gfx::SkColorToCalibratedNSColor( + message_center::kDimTextColor)]; + [contextMessage_ setFont: + [NSFont messageFontOfSize:message_center::kMessageFontSize]]; +} + +- (NSTextView*)newLabelWithFrame:(NSRect)frame { + NSTextView* label = [[NSTextView alloc] initWithFrame:frame]; [label setDrawsBackground:NO]; - [label setBezeled:NO]; [label setEditable:NO]; [label setSelectable:NO]; + [label setTextContainerInset:NSMakeSize(0.0f, 0.0f)]; + [[label textContainer] setLineFragmentPadding:0.0f]; return label; } @@ -638,27 +685,33 @@ } - (string16)wrapText:(const string16&)text - forField:(NSTextField*)field + forFont:(NSFont*)nsfont maxNumberOfLines:(size_t)lines { - gfx::Font font([field font]); + if (text.empty()) + return text; + gfx::Font font(nsfont); int width = NSWidth([self currentContentRect]); int height = (lines + 1) * font.GetHeight(); std::vector<string16> wrapped; - ui::ElideRectangleText(text, font, width, height, - ui::WRAP_LONG_WORDS, &wrapped); + gfx::ElideRectangleText(text, font, width, height, + gfx::WRAP_LONG_WORDS, &wrapped); + + // This could be possible when the input text contains only spaces. + if (wrapped.empty()) + return string16(); if (wrapped.size() > lines) { // Add an ellipsis to the last line. If this ellipsis makes the last line - // too wide, that line will be further elided by the ui::ElideText below. - string16 last = wrapped[lines - 1] + UTF8ToUTF16(ui::kEllipsis); + // too wide, that line will be further elided by the gfx::ElideText below. + string16 last = wrapped[lines - 1] + UTF8ToUTF16(gfx::kEllipsis); if (font.GetStringWidth(last) > width) - last = ui::ElideText(last, font, width, ui::ELIDE_AT_END); + last = gfx::ElideText(last, font, width, gfx::ELIDE_AT_END); wrapped.resize(lines - 1); wrapped.push_back(last); } - return JoinString(wrapped, '\n'); + return lines == 1 ? wrapped[0] : JoinString(wrapped, '\n'); } @end diff --git a/chromium/ui/message_center/cocoa/notification_controller_unittest.mm b/chromium/ui/message_center/cocoa/notification_controller_unittest.mm index ea7968e96e7..8ba6026782d 100644 --- a/chromium/ui/message_center/cocoa/notification_controller_unittest.mm +++ b/chromium/ui/message_center/cocoa/notification_controller_unittest.mm @@ -76,16 +76,20 @@ class MockMessageCenter : public message_center::FakeMessageCenter { return icon_.get(); } -- (NSTextField*)titleView { +- (NSTextView*)titleView { return title_.get(); } -- (NSTextField*)messageView { +- (NSTextView*)messageView { return message_.get(); } -- (NSView*)listItemView { - return listItemView_.get(); +- (NSTextView*)contextMessageView { + return contextMessage_.get(); +} + +- (NSView*)listView { + return listView_.get(); } @end @@ -105,7 +109,7 @@ TEST_F(NotificationControllerTest, BasicLayout) { ASCIIToUTF16("Jonathan and 5 others"), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); notification->set_icon(gfx::Image([TestIcon() retain])); @@ -116,9 +120,9 @@ TEST_F(NotificationControllerTest, BasicLayout) { [controller view]; EXPECT_EQ(TestIcon(), [[controller iconView] image]); - EXPECT_EQ(base::SysNSStringToUTF16([[controller titleView] stringValue]), + EXPECT_EQ(base::SysNSStringToUTF16([[controller titleView] string]), notification->title()); - EXPECT_EQ(base::SysNSStringToUTF16([[controller messageView] stringValue]), + EXPECT_EQ(base::SysNSStringToUTF16([[controller messageView] string]), notification->message()); EXPECT_EQ(controller.get(), [[controller closeButton] target]); } @@ -135,7 +139,7 @@ TEST_F(NotificationControllerTest, OverflowText) { "entire thing?"), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); base::scoped_nsobject<MCNotificationController> controller( @@ -156,7 +160,7 @@ TEST_F(NotificationControllerTest, Close) { string16(), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); MockMessageCenter message_center; @@ -183,7 +187,7 @@ TEST_F(NotificationControllerTest, Update) { "default bounds."), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); base::scoped_nsobject<MCNotificationController> controller( @@ -219,7 +223,7 @@ TEST_F(NotificationControllerTest, Buttons) { string16(), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), optional, NULL)); MockMessageCenter message_center; @@ -244,7 +248,7 @@ TEST_F(NotificationControllerTest, Image) { string16(), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); NSImage* image = [NSImage imageNamed:NSImageNameFolder]; @@ -272,6 +276,11 @@ TEST_F(NotificationControllerTest, List) { UTF8ToUTF16("Second title"), UTF8ToUTF16("second slightly longer message")); optional.items.push_back(item2); + message_center::NotificationItem item3( + UTF8ToUTF16(""), // Test for empty string. + UTF8ToUTF16(" ")); // Test for string containing only spaces. + optional.items.push_back(item3); + optional.context_message = UTF8ToUTF16("Context Message"); scoped_ptr<message_center::Notification> notification( new message_center::Notification( @@ -281,7 +290,7 @@ TEST_F(NotificationControllerTest, List) { UTF8ToUTF16("Notification Message - should be hidden"), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), optional, NULL)); @@ -293,8 +302,9 @@ TEST_F(NotificationControllerTest, List) { EXPECT_FALSE([[controller titleView] isHidden]); EXPECT_TRUE([[controller messageView] isHidden]); + EXPECT_FALSE([[controller contextMessageView] isHidden]); - EXPECT_EQ(2u, [[[controller listItemView] subviews] count]); - EXPECT_LT(NSMaxY([[controller listItemView] frame]), + EXPECT_EQ(3u, [[[controller listView] subviews] count]); + EXPECT_LT(NSMaxY([[controller listView] frame]), NSMinY([[controller titleView] frame])); } diff --git a/chromium/ui/message_center/cocoa/popup_collection_unittest.mm b/chromium/ui/message_center/cocoa/popup_collection_unittest.mm index 105c824e875..3ec7c3318f2 100644 --- a/chromium/ui/message_center/cocoa/popup_collection_unittest.mm +++ b/chromium/ui/message_center/cocoa/popup_collection_unittest.mm @@ -51,7 +51,7 @@ class PopupCollectionTest : public ui::CocoaTest { " be displayed"), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); center_->AddNotification(notification.Pass()); @@ -63,7 +63,7 @@ class PopupCollectionTest : public ui::CocoaTest { ASCIIToUTF16("This is the second notification."), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); center_->AddNotification(notification.Pass()); @@ -76,10 +76,11 @@ class PopupCollectionTest : public ui::CocoaTest { "that has a much longer body " "than the other notifications. It " "may not fit on the screen if we " - "set the screen size too small."), + "set the screen size too small or " + "if the notification is way too big"), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); center_->AddNotification(notification.Pass()); @@ -134,7 +135,7 @@ TEST_F(PopupCollectionTest, AttemptFourOneOffscreen) { ASCIIToUTF16("This is the fourth notification."), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); center_->AddNotification(notification.Pass()); @@ -183,7 +184,7 @@ TEST_F(PopupCollectionTest, LayoutSpacing) { ASCIIToUTF16("This is the fourth notification."), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), optional, NULL)); center_->AddNotification(notification.Pass()); @@ -221,7 +222,7 @@ TEST_F(PopupCollectionTest, TinyScreen) { " be displayed"), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); center_->AddNotification(notification.Pass()); @@ -243,7 +244,7 @@ TEST_F(PopupCollectionTest, TinyScreen) { "long notification."), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); center_->UpdateNotification("1", notification.Pass()); @@ -287,7 +288,7 @@ TEST_F(PopupCollectionTest, UpdateIconAndBody) { "longer body"), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); center_->AddNotification(notification.Pass()); @@ -316,7 +317,7 @@ TEST_F(PopupCollectionTest, CloseCollectionBeforeNewPopupAnimationEnds) { " be displayed"), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); center_->AddNotification(notification.Pass()); @@ -349,7 +350,7 @@ TEST_F(PopupCollectionTest, CloseCollectionBeforeUpdatePopupAnimationEnds) { ASCIIToUTF16("New message."), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); center_->UpdateNotification("1", notification.Pass()); diff --git a/chromium/ui/message_center/cocoa/popup_controller_unittest.mm b/chromium/ui/message_center/cocoa/popup_controller_unittest.mm index 41f627937e7..c39d1631288 100644 --- a/chromium/ui/message_center/cocoa/popup_controller_unittest.mm +++ b/chromium/ui/message_center/cocoa/popup_controller_unittest.mm @@ -23,7 +23,7 @@ TEST_F(PopupControllerTest, Creation) { ASCIIToUTF16("Jonathan and 5 others"), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); diff --git a/chromium/ui/message_center/cocoa/tray_controller.mm b/chromium/ui/message_center/cocoa/tray_controller.mm index f911ec98353..672525f29dc 100644 --- a/chromium/ui/message_center/cocoa/tray_controller.mm +++ b/chromium/ui/message_center/cocoa/tray_controller.mm @@ -105,7 +105,7 @@ // The settings bubble data structures assume that the settings dialog is // visible only for short periods of time: There's a fixed list of permissions // for example. - [viewController_ hideSettings:self]; + [viewController_ cleanupSettings]; tray_->HideMessageCenterBubble(); } diff --git a/chromium/ui/message_center/cocoa/tray_view_controller.h b/chromium/ui/message_center/cocoa/tray_view_controller.h index cb9379b877c..d5f9f1f8876 100644 --- a/chromium/ui/message_center/cocoa/tray_view_controller.h +++ b/chromium/ui/message_center/cocoa/tray_view_controller.h @@ -134,7 +134,11 @@ MESSAGE_CENTER_EXPORT - (void)updateSettings; // Hides the settings dialog if it's open. -- (void)hideSettings:(id)sender; +- (void)showMessages:(id)sender; + +// Cleans up settings data structures. Called when messages are shown and when +// closing the center directly from the settings. +- (void)cleanupSettings; // Scroll to the topmost notification in the tray. - (void)scrollToTop; diff --git a/chromium/ui/message_center/cocoa/tray_view_controller.mm b/chromium/ui/message_center/cocoa/tray_view_controller.mm index 67b0cdf712d..17c24f73657 100644 --- a/chromium/ui/message_center/cocoa/tray_view_controller.mm +++ b/chromium/ui/message_center/cocoa/tray_view_controller.mm @@ -126,6 +126,9 @@ const CGFloat kTrayBottomMargin = 75; animation_.reset(); } if (clearAllInProgress_) { + // To stop chain of clearOneNotification calls to start new animations. + [NSObject cancelPreviousPerformRequestsWithTarget:self]; + for (NSViewAnimation* animation in clearAllAnimations_.get()) { [animation stopAnimation]; [animation setDelegate:nil]; @@ -277,7 +280,7 @@ const CGFloat kTrayBottomMargin = 75; - (void)showSettings:(id)sender { if (settingsController_) - return [self hideSettings:sender]; + return [self showMessages:sender]; message_center::NotifierSettingsProvider* provider = messageCenter_->GetNotifierSettingsProvider(); @@ -297,6 +300,7 @@ const CGFloat kTrayBottomMargin = 75; [scrollView_ setHidden:YES]; [[[self view] window] recalculateKeyViewLoop]; + messageCenter_->SetVisibility(message_center::VISIBILITY_SETTINGS); [self updateTrayViewAndWindow]; } @@ -312,7 +316,14 @@ const CGFloat kTrayBottomMargin = 75; [self updateTrayViewAndWindow]; } -- (void)hideSettings:(id)sender { +- (void)showMessages:(id)sender { + messageCenter_->SetVisibility(message_center::VISIBILITY_MESSAGE_CENTER); + [self cleanupSettings]; + [[[self view] window] recalculateKeyViewLoop]; + [self updateTrayViewAndWindow]; +} + +- (void)cleanupSettings { [scrollView_ setHidden:NO]; [[settingsController_ view] removeFromSuperview]; @@ -324,8 +335,6 @@ const CGFloat kTrayBottomMargin = 75; [backButton_ setHidden:YES]; [clearAllButton_ setEnabled:YES]; - [[[self view] window] recalculateKeyViewLoop]; - [self updateTrayViewAndWindow]; } - (void)scrollToTop { @@ -424,7 +433,7 @@ const CGFloat kTrayBottomMargin = 75; rb.GetNativeImageNamed(IDR_NOTIFICATION_ARROW_HOVER).ToNSImage()]; [backButton_ setPressedImage: rb.GetNativeImageNamed(IDR_NOTIFICATION_ARROW_PRESSED).ToNSImage()]; - [backButton_ setAction:@selector(hideSettings:)]; + [backButton_ setAction:@selector(showMessages:)]; configureButton(backButton_); [backButton_ setHidden:YES]; [backButton_ setKeyEquivalent:@"\e"]; diff --git a/chromium/ui/message_center/cocoa/tray_view_controller_unittest.mm b/chromium/ui/message_center/cocoa/tray_view_controller_unittest.mm index 6c82777be9d..03207d965d2 100644 --- a/chromium/ui/message_center/cocoa/tray_view_controller_unittest.mm +++ b/chromium/ui/message_center/cocoa/tray_view_controller_unittest.mm @@ -71,7 +71,7 @@ TEST_F(TrayViewControllerTest, AddRemoveOne) { ASCIIToUTF16("This is a simple test."), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); center_->AddNotification(notification_data.Pass()); @@ -105,7 +105,7 @@ TEST_F(TrayViewControllerTest, AddThreeClearAll) { ASCIIToUTF16("This is a simple test."), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); center_->AddNotification(notification.Pass()); @@ -116,7 +116,7 @@ TEST_F(TrayViewControllerTest, AddThreeClearAll) { ASCIIToUTF16("This is a simple test."), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); center_->AddNotification(notification.Pass()); @@ -127,7 +127,7 @@ TEST_F(TrayViewControllerTest, AddThreeClearAll) { ASCIIToUTF16("This is a simple test."), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); center_->AddNotification(notification.Pass()); @@ -160,7 +160,7 @@ TEST_F(TrayViewControllerTest, NoClearAllWhenNoNotifications) { ASCIIToUTF16("This is a simple test."), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); center_->AddNotification(notification.Pass()); @@ -179,7 +179,7 @@ TEST_F(TrayViewControllerTest, NoClearAllWhenNoNotifications) { ASCIIToUTF16("This is a simple test."), gfx::Image(), string16(), - std::string(), + message_center::NotifierId(), message_center::RichNotificationData(), NULL)); center_->AddNotification(notification.Pass()); @@ -225,13 +225,15 @@ TEST_F(TrayViewControllerTest, Settings) { EXPECT_EQ(0, provider.closed_called_count()); [tray_ showSettings:nil]; + EXPECT_FALSE(center_->IsMessageCenterVisible()); // There are 0 notifications, but 2 notifiers. The settings pane should be // higher than the empty tray bubble. EXPECT_LT(trayHeight, NSHeight([[tray_ view] frame])); - [tray_ hideSettings:nil]; + [tray_ showMessages:nil]; EXPECT_EQ(1, provider.closed_called_count()); + EXPECT_TRUE(center_->IsMessageCenterVisible()); // The tray should be back at its previous height now. EXPECT_EQ(trayHeight, NSHeight([[tray_ view] frame])); diff --git a/chromium/ui/message_center/dummy_message_center.cc b/chromium/ui/message_center/dummy_message_center.cc index 27ecc912eb4..54b30825113 100644 --- a/chromium/ui/message_center/dummy_message_center.cc +++ b/chromium/ui/message_center/dummy_message_center.cc @@ -39,7 +39,4 @@ MessageCenter::MessageCenter() { MessageCenter::~MessageCenter() { } -MessageCenter::Delegate::~Delegate() { -} - } // namespace message_center diff --git a/chromium/ui/message_center/fake_message_center.cc b/chromium/ui/message_center/fake_message_center.cc index 4deff26b138..eaa4c42cc88 100644 --- a/chromium/ui/message_center/fake_message_center.cc +++ b/chromium/ui/message_center/fake_message_center.cc @@ -19,7 +19,11 @@ void FakeMessageCenter::AddObserver(MessageCenterObserver* observer) { void FakeMessageCenter::RemoveObserver(MessageCenterObserver* observer) { } -void FakeMessageCenter::SetDelegate(Delegate* delegate) { +void FakeMessageCenter::AddNotificationBlocker(NotificationBlocker* blocker) { +} + +void FakeMessageCenter::RemoveNotificationBlocker( + NotificationBlocker* blocker) { } size_t FakeMessageCenter::NotificationCount() const { @@ -83,13 +87,8 @@ void FakeMessageCenter::SetNotificationButtonIcon( const gfx::Image& image) { } -void FakeMessageCenter::DisableNotificationsByExtension(const std::string& id) { -} - -void FakeMessageCenter::DisableNotificationsByUrl(const std::string& id) { -} - -void FakeMessageCenter::ShowNotificationSettings(const std::string& id) { +void FakeMessageCenter::DisableNotificationsByNotifier( + const NotifierId& notifier_id) { } void FakeMessageCenter::ExpandNotification(const std::string& id) { @@ -124,7 +123,7 @@ void FakeMessageCenter::EnterQuietModeWithExpire( const base::TimeDelta& expires_in) { } -void FakeMessageCenter::SetMessageCenterVisible(bool visible) { +void FakeMessageCenter::SetVisibility(Visibility visible) { } bool FakeMessageCenter::IsMessageCenterVisible() { diff --git a/chromium/ui/message_center/fake_message_center.h b/chromium/ui/message_center/fake_message_center.h index ebb9be210d4..e7fbddcbd9e 100644 --- a/chromium/ui/message_center/fake_message_center.h +++ b/chromium/ui/message_center/fake_message_center.h @@ -6,6 +6,7 @@ #define UI_MESSAGE_CENTER_FAKE_MESSAGE_CENTER_H_ #include "ui/message_center/message_center.h" +#include "ui/message_center/message_center_types.h" namespace message_center { @@ -18,9 +19,10 @@ class FakeMessageCenter : public MessageCenter { virtual ~FakeMessageCenter(); // Overridden from FakeMessageCenter. - virtual void SetDelegate(Delegate* delegate) OVERRIDE; virtual void AddObserver(MessageCenterObserver* observer) OVERRIDE; virtual void RemoveObserver(MessageCenterObserver* observer) OVERRIDE; + virtual void AddNotificationBlocker(NotificationBlocker* blocker) OVERRIDE; + virtual void RemoveNotificationBlocker(NotificationBlocker* blocker) OVERRIDE; virtual size_t NotificationCount() const OVERRIDE; virtual size_t UnreadNotificationCount() const OVERRIDE; virtual bool HasPopupNotifications() const OVERRIDE; @@ -45,9 +47,8 @@ class FakeMessageCenter : public MessageCenter { virtual void SetNotificationButtonIcon(const std::string& notification_id, int button_index, const gfx::Image& image) OVERRIDE; - virtual void DisableNotificationsByExtension(const std::string& id) OVERRIDE; - virtual void DisableNotificationsByUrl(const std::string& id) OVERRIDE; - virtual void ShowNotificationSettings(const std::string& id) OVERRIDE; + virtual void DisableNotificationsByNotifier( + const NotifierId& notifier_id) OVERRIDE; virtual void ExpandNotification(const std::string& id) OVERRIDE; virtual void ClickOnNotification(const std::string& id) OVERRIDE; virtual void ClickOnNotificationButton(const std::string& id, @@ -61,7 +62,7 @@ class FakeMessageCenter : public MessageCenter { virtual void SetQuietMode(bool in_quiet_mode) OVERRIDE; virtual void EnterQuietModeWithExpire( const base::TimeDelta& expires_in) OVERRIDE; - virtual void SetMessageCenterVisible(bool visible) OVERRIDE; + virtual void SetVisibility(Visibility visible) OVERRIDE; virtual bool IsMessageCenterVisible() OVERRIDE; virtual void RestartPopupTimers() OVERRIDE; virtual void PausePopupTimers() OVERRIDE; diff --git a/chromium/ui/message_center/fake_notifier_settings_provider.cc b/chromium/ui/message_center/fake_notifier_settings_provider.cc index d8054cab2e5..f593ed9820f 100644 --- a/chromium/ui/message_center/fake_notifier_settings_provider.cc +++ b/chromium/ui/message_center/fake_notifier_settings_provider.cc @@ -15,7 +15,9 @@ FakeNotifierSettingsProvider::NotifierGroupItem::NotifierGroupItem() { FakeNotifierSettingsProvider::NotifierGroupItem::~NotifierGroupItem() { } -FakeNotifierSettingsProvider::FakeNotifierSettingsProvider() { +FakeNotifierSettingsProvider::FakeNotifierSettingsProvider() + : closed_called_count_(0), + active_item_index_(0) { } FakeNotifierSettingsProvider::FakeNotifierSettingsProvider( diff --git a/chromium/ui/message_center/fake_notifier_settings_provider.h b/chromium/ui/message_center/fake_notifier_settings_provider.h index 85348f75924..b71a7e9fb28 100644 --- a/chromium/ui/message_center/fake_notifier_settings_provider.h +++ b/chromium/ui/message_center/fake_notifier_settings_provider.h @@ -14,7 +14,8 @@ namespace message_center { class FakeNotifierSettingsProvider : public NotifierSettingsProvider { public: FakeNotifierSettingsProvider(); - FakeNotifierSettingsProvider(const std::vector<Notifier*>& notifiers); + explicit FakeNotifierSettingsProvider( + const std::vector<Notifier*>& notifiers); virtual ~FakeNotifierSettingsProvider(); virtual size_t GetNotifierGroupCount() const OVERRIDE; diff --git a/chromium/ui/message_center/message_center.cc b/chromium/ui/message_center/message_center.cc index dc0de1c3103..82f2e8443aa 100644 --- a/chromium/ui/message_center/message_center.cc +++ b/chromium/ui/message_center/message_center.cc @@ -11,11 +11,6 @@ namespace message_center { //------------------------------------------------------------------------------ -MessageCenter::Delegate::~Delegate() { -} - -//------------------------------------------------------------------------------ - namespace { static MessageCenter* g_message_center; } diff --git a/chromium/ui/message_center/message_center.gyp b/chromium/ui/message_center/message_center.gyp index dc1f1ab6fea..46f4d5b111d 100644 --- a/chromium/ui/message_center/message_center.gyp +++ b/chromium/ui/message_center/message_center.gyp @@ -54,10 +54,13 @@ 'message_center_tray.cc', 'message_center_tray.h', 'message_center_tray_delegate.h', + 'message_center_types.h', 'message_center_util.cc', 'message_center_util.h', 'notification.cc', 'notification.h', + 'notification_blocker.cc', + 'notification_blocker.h', 'notification_list.cc', 'notification_list.h', 'notification_types.cc', diff --git a/chromium/ui/message_center/message_center.h b/chromium/ui/message_center/message_center.h index c0556647148..ebe90d23232 100644 --- a/chromium/ui/message_center/message_center.h +++ b/chromium/ui/message_center/message_center.h @@ -11,6 +11,7 @@ #include "base/observer_list.h" #include "ui/gfx/native_widget_types.h" #include "ui/message_center/message_center_export.h" +#include "ui/message_center/message_center_types.h" #include "ui/message_center/notification_list.h" #include "ui/message_center/notification_types.h" @@ -24,12 +25,11 @@ class DictionaryValue; // [Add|Remove|Update]Notification to create and update notifications in the // list. It also sends those changes to its observers when a notification // is shown, closed, or clicked on. -// It can also implement Delegate to ask platform-dependent features like -// disabling extensions or opening settings. namespace message_center { class MessageCenterObserver; +class NotificationBlocker; class NotificationList; class NotifierSettingsDelegate; class NotifierSettingsProvider; @@ -39,33 +39,13 @@ class MESSAGE_CENTER_EXPORT MessageCenter { // Creates the global message center object. static void Initialize(); - // Returns the global message center object. Initialize must be called first. + // Returns the global message center object. Returns NULL if Initialize is not + // called. static MessageCenter* Get(); // Destroys the global message_center object. static void Shutdown(); - class MESSAGE_CENTER_EXPORT Delegate { - public: - virtual ~Delegate(); - - // Request to disable the extension associated with |notification_id|. - virtual void DisableExtension(const std::string& notification_id) = 0; - - // Request to disable notifications from the source of |notification_id|. - virtual void DisableNotificationsFromSource( - const std::string& notification_id) = 0; - - // Request to show the notification settings (|notification_id| is used - // to identify the requesting browser context). - virtual void ShowSettings(const std::string& notification_id) = 0; - }; - - // Called to set the delegate. Generally called only once, except in tests. - // Changing the delegate does not affect notifications in its - // NotificationList. - virtual void SetDelegate(Delegate* delegate) = 0; - // Management of the observer list. virtual void AddObserver(MessageCenterObserver* observer) = 0; virtual void RemoveObserver(MessageCenterObserver* observer) = 0; @@ -83,6 +63,10 @@ class MESSAGE_CENTER_EXPORT MessageCenter { // Gets all notifications being shown as popups. virtual NotificationList::PopupNotifications GetPopupNotifications() = 0; + // Management of NotificaitonBlockers. + virtual void AddNotificationBlocker(NotificationBlocker* blocker) = 0; + virtual void RemoveNotificationBlocker(NotificationBlocker* blocker) = 0; + // Basic operations of notification: add/remove/update. // Adds a new notification. @@ -115,17 +99,8 @@ class MESSAGE_CENTER_EXPORT MessageCenter { // and settings. // Searches through the notifications and disables any that match the // extension id given. - virtual void DisableNotificationsByExtension(const std::string& id) = 0; - - // Disables all notifications that match the given url by querying the - // delegate and also by matching display_source. - // TODO(dewittj): Is display_source matching necessary? - virtual void DisableNotificationsByUrl(const std::string& url) = 0; - - // TODO(mukai): settings can be in another class? - // Shows the settings for a web notification (profile is identified by the - // given notification id). - virtual void ShowNotificationSettings(const std::string& id) = 0; + virtual void DisableNotificationsByNotifier( + const NotifierId& notifier_id) = 0; // Reformat a notification to show its entire text content. virtual void ExpandNotification(const std::string& id) = 0; @@ -168,7 +143,7 @@ class MESSAGE_CENTER_EXPORT MessageCenter { // Informs the notification list whether the message center is visible. // This affects whether or not a message has been "read". - virtual void SetMessageCenterVisible(bool visible) = 0; + virtual void SetVisibility(Visibility visible) = 0; // Allows querying the visibility of the center. virtual bool IsMessageCenterVisible() = 0; diff --git a/chromium/ui/message_center/message_center_impl.cc b/chromium/ui/message_center/message_center_impl.cc index c1d0179dc00..2d8c9f22518 100644 --- a/chromium/ui/message_center/message_center_impl.cc +++ b/chromium/ui/message_center/message_center_impl.cc @@ -4,9 +4,13 @@ #include "ui/message_center/message_center_impl.h" +#include <algorithm> + #include "base/observer_list.h" #include "ui/message_center/message_center_style.h" +#include "ui/message_center/message_center_types.h" #include "ui/message_center/notification.h" +#include "ui/message_center/notification_blocker.h" #include "ui/message_center/notification_list.h" #include "ui/message_center/notification_types.h" @@ -27,6 +31,35 @@ namespace message_center { namespace internal { //////////////////////////////////////////////////////////////////////////////// +// NotificationQueueItem + +struct NotificationQueueItem { + public: + Notification* notification; + bool is_update; + std::string pre_update_id; +}; + +void DeleteQueueNotification(NotificationQueueItem item) { + if (item.notification) + delete item.notification; +} + + +//////////////////////////////////////////////////////////////////////////////// +// NotificationFinder + +struct NotificationFinder { + explicit NotificationFinder(const std::string& id) : id(id) {} + bool operator()(const NotificationQueueItem& item) { + DCHECK(item.notification); + return item.notification->id() == id; + } + + std::string id; +}; + +//////////////////////////////////////////////////////////////////////////////// // PopupTimer PopupTimer::PopupTimer(const std::string& id, @@ -194,13 +227,16 @@ void PopupTimersController::OnNotificationRemoved(const std::string& id, MessageCenterImpl::MessageCenterImpl() : MessageCenter(), popup_timers_controller_(new internal::PopupTimersController(this)), - delegate_(NULL), settings_provider_(NULL) { notification_list_.reset(new NotificationList()); } MessageCenterImpl::~MessageCenterImpl() { notification_list_.reset(); + for_each(notification_queue_.begin(), + notification_queue_.end(), + internal::DeleteQueueNotification); + notification_queue_.clear(); } void MessageCenterImpl::AddObserver(MessageCenterObserver* observer) { @@ -211,13 +247,41 @@ void MessageCenterImpl::RemoveObserver(MessageCenterObserver* observer) { observer_list_.RemoveObserver(observer); } -void MessageCenterImpl::SetDelegate(Delegate* delegate) { - delegate_ = delegate; +void MessageCenterImpl::AddNotificationBlocker(NotificationBlocker* blocker) { + if (std::find(blockers_.begin(), blockers_.end(), blocker) != + blockers_.end()) { + return; + } + blocker->AddObserver(this); + blockers_.push_back(blocker); +} + +void MessageCenterImpl::RemoveNotificationBlocker( + NotificationBlocker* blocker) { + std::vector<NotificationBlocker*>::iterator iter = + std::find(blockers_.begin(), blockers_.end(), blocker); + if (iter == blockers_.end()) + return; + blocker->RemoveObserver(this); + blockers_.erase(iter); } -void MessageCenterImpl::SetMessageCenterVisible(bool visible) { +void MessageCenterImpl::OnBlockingStateChanged() { + std::list<std::string> blocked_ids; + NotificationList::PopupNotifications popups = + notification_list_->GetPopupNotifications(blockers_, &blocked_ids); + + for (std::list<std::string>::const_iterator iter = blocked_ids.begin(); + iter != blocked_ids.end(); ++iter) { + MarkSinglePopupAsShown((*iter), true); + } +} + +void MessageCenterImpl::SetVisibility(Visibility visibility) { std::set<std::string> updated_ids; - notification_list_->SetMessageCenterVisible(visible, &updated_ids); + notification_list_->SetMessageCenterVisible( + (visibility == VISIBILITY_MESSAGE_CENTER), &updated_ids); + for (std::set<std::string>::const_iterator iter = updated_ids.begin(); iter != updated_ids.end(); ++iter) { @@ -225,10 +289,26 @@ void MessageCenterImpl::SetMessageCenterVisible(bool visible) { MessageCenterObserver, observer_list_, OnNotificationUpdated(*iter)); } - if (!visible) { - FOR_EACH_OBSERVER( - MessageCenterObserver, observer_list_, OnNotificationCenterClosed()); + if (visibility == VISIBILITY_TRANSIENT) { + for (std::list<internal::NotificationQueueItem>::const_iterator iter = + notification_queue_.begin(); + iter != notification_queue_.end(); + ++iter) { + // Warning: After this line, the queue will no longer own the + // notifications contained. + if ((*iter).is_update) + UpdateNotification((*iter).pre_update_id, + scoped_ptr<Notification>((*iter).notification)); + else + AddNotification(scoped_ptr<Notification>((*iter).notification)); + } + // This does not delete the internal notification pointers since they are + // now owned by the notification list. + notification_queue_.clear(); } + FOR_EACH_OBSERVER(MessageCenterObserver, + observer_list_, + OnCenterVisibilityChanged(visibility)); } bool MessageCenterImpl::IsMessageCenterVisible() { @@ -244,7 +324,7 @@ size_t MessageCenterImpl::UnreadNotificationCount() const { } bool MessageCenterImpl::HasPopupNotifications() const { - return notification_list_->HasPopupNotifications(); + return notification_list_->HasPopupNotifications(blockers_); } bool MessageCenterImpl::HasNotification(const std::string& id) { @@ -267,7 +347,7 @@ const NotificationList::Notifications& MessageCenterImpl::GetNotifications() { NotificationList::PopupNotifications MessageCenterImpl::GetPopupNotifications() { - return notification_list_->GetPopupNotifications(); + return notification_list_->GetPopupNotifications(blockers_, NULL); } //------------------------------------------------------------------------------ @@ -275,6 +355,27 @@ NotificationList::PopupNotifications void MessageCenterImpl::AddNotification(scoped_ptr<Notification> notification) { DCHECK(notification.get()); + for (size_t i = 0; i < blockers_.size(); ++i) + blockers_[i]->CheckState(); + + if (notification_list_->is_message_center_visible()) { + std::list<internal::NotificationQueueItem>::iterator iter = std::find_if( + notification_queue_.begin(), + notification_queue_.end(), + internal::NotificationFinder(notification->id())); + if (iter != notification_queue_.end()) { + internal::DeleteQueueNotification(*iter); + notification_queue_.erase(iter); + } + internal::NotificationQueueItem item = { + notification.release(), + false, + std::string() + }; + notification_queue_.push_back(item); + return; + } + // Sometimes the notification can be added with the same id and the // |notification_list| will replace the notification instead of adding new. // This is essentially an update rather than addition. @@ -294,6 +395,38 @@ void MessageCenterImpl::AddNotification(scoped_ptr<Notification> notification) { void MessageCenterImpl::UpdateNotification( const std::string& old_id, scoped_ptr<Notification> new_notification) { + for (size_t i = 0; i < blockers_.size(); ++i) + blockers_[i]->CheckState(); + + // We will allow notifications that are progress types (and stay progress + // types) to be updated even if the message center is open. + bool update_keeps_progress_type = + new_notification->type() == NOTIFICATION_TYPE_PROGRESS; + if (!notification_list_->HasNotificationOfType(old_id, + NOTIFICATION_TYPE_PROGRESS)) { + update_keeps_progress_type = false; + } + + // Updates are allowed only for progress notifications. + if (notification_list_->is_message_center_visible() && + !update_keeps_progress_type) { + std::list<internal::NotificationQueueItem>::iterator iter = std::find_if( + notification_queue_.begin(), + notification_queue_.end(), + internal::NotificationFinder(old_id)); + if (iter != notification_queue_.end()) { + internal::DeleteQueueNotification(*iter); + notification_queue_.erase(iter); + } + internal::NotificationQueueItem item = { + new_notification.release(), + true, + old_id + }; + notification_queue_.push_back(item); + return; + } + std::string new_id = new_notification->id(); notification_list_->UpdateNotificationMessage(old_id, new_notification.Pass()); @@ -310,6 +443,15 @@ void MessageCenterImpl::UpdateNotification( void MessageCenterImpl::RemoveNotification(const std::string& id, bool by_user) { + std::list<internal::NotificationQueueItem>::iterator iter = std::find_if( + notification_queue_.begin(), + notification_queue_.end(), + internal::NotificationFinder(id)); + if (iter != notification_queue_.end()) { + DeleteQueueNotification(*iter); + notification_queue_.erase(iter); + } + if (!HasNotification(id)) return; @@ -335,6 +477,9 @@ void MessageCenterImpl::RemoveAllNotifications(bool by_user) { for (NotificationList::Notifications::const_iterator iter = notifications.begin(); iter != notifications.end(); ++iter) { ids.insert((*iter)->id()); + NotificationDelegate* delegate = (*iter)->delegate(); + if (delegate) + delegate->Close(by_user); } notification_list_->RemoveAllNotifications(); @@ -348,7 +493,17 @@ void MessageCenterImpl::RemoveAllNotifications(bool by_user) { void MessageCenterImpl::SetNotificationIcon(const std::string& notification_id, const gfx::Image& image) { - if (notification_list_->SetNotificationIcon(notification_id, image)) { + std::list<internal::NotificationQueueItem>::iterator iter = std::find_if( + notification_queue_.begin(), + notification_queue_.end(), + internal::NotificationFinder(notification_id)); + bool found = iter != notification_queue_.end(); + if (found) + iter->notification->set_icon(image); + else + found = notification_list_->SetNotificationIcon(notification_id, image); + + if (found) { FOR_EACH_OBSERVER(MessageCenterObserver, observer_list_, OnNotificationUpdated(notification_id)); } @@ -374,27 +529,16 @@ void MessageCenterImpl::SetNotificationButtonIcon( } } -void MessageCenterImpl::DisableNotificationsByExtension( - const std::string& id) { - if (delegate_) - delegate_->DisableExtension(id); - - NotificationList::Notifications notifications = - notification_list_->GetNotificationsByExtension(id); - for (NotificationList::Notifications::const_iterator iter = - notifications.begin(); iter != notifications.end();) { - std::string id = (*iter)->id(); - iter++; - RemoveNotification(id, false); +void MessageCenterImpl::DisableNotificationsByNotifier( + const NotifierId& notifier_id) { + if (settings_provider_) { + // TODO(mukai): SetNotifierEnabled can just accept notifier_id? + Notifier notifier(notifier_id, base::string16(), true); + settings_provider_->SetNotifierEnabled(notifier, false); } -} - -void MessageCenterImpl::DisableNotificationsByUrl(const std::string& id) { - if (delegate_) - delegate_->DisableNotificationsFromSource(id); NotificationList::Notifications notifications = - notification_list_->GetNotificationsBySource(id); + notification_list_->GetNotificationsByNotifierId(notifier_id); for (NotificationList::Notifications::const_iterator iter = notifications.begin(); iter != notifications.end();) { std::string id = (*iter)->id(); @@ -403,11 +547,6 @@ void MessageCenterImpl::DisableNotificationsByUrl(const std::string& id) { } } -void MessageCenterImpl::ShowNotificationSettings(const std::string& id) { - if (delegate_) - delegate_->ShowSettings(id); -} - void MessageCenterImpl::ExpandNotification(const std::string& id) { if (!HasNotification(id)) return; @@ -477,12 +616,33 @@ NotifierSettingsProvider* MessageCenterImpl::GetNotifierSettingsProvider() { } void MessageCenterImpl::SetQuietMode(bool in_quiet_mode) { - notification_list_->SetQuietMode(in_quiet_mode); + if (in_quiet_mode != notification_list_->quiet_mode()) { + notification_list_->SetQuietMode(in_quiet_mode); + FOR_EACH_OBSERVER(MessageCenterObserver, + observer_list_, + OnQuietModeChanged(in_quiet_mode)); + } + quiet_mode_timer_.reset(); } void MessageCenterImpl::EnterQuietModeWithExpire( const base::TimeDelta& expires_in) { - notification_list_->EnterQuietModeWithExpire(expires_in); + if (quiet_mode_timer_.get()) { + // Note that the capital Reset() is the method to restart the timer, not + // scoped_ptr::reset(). + quiet_mode_timer_->Reset(); + } else { + notification_list_->SetQuietMode(true); + FOR_EACH_OBSERVER( + MessageCenterObserver, observer_list_, OnQuietModeChanged(true)); + + quiet_mode_timer_.reset(new base::OneShotTimer<MessageCenterImpl>); + quiet_mode_timer_->Start( + FROM_HERE, + expires_in, + base::Bind( + &MessageCenterImpl::SetQuietMode, base::Unretained(this), false)); + } } void MessageCenterImpl::RestartPopupTimers() { diff --git a/chromium/ui/message_center/message_center_impl.h b/chromium/ui/message_center/message_center_impl.h index 412e0b3b15e..b57f5322858 100644 --- a/chromium/ui/message_center/message_center_impl.h +++ b/chromium/ui/message_center/message_center_impl.h @@ -6,6 +6,7 @@ #define UI_MESSAGE_CENTER_MESSAGE_CENTER_IMPL_H_ #include <string> +#include <vector> #include "base/memory/weak_ptr.h" #include "base/stl_util.h" @@ -13,12 +14,15 @@ #include "base/timer/timer.h" #include "ui/message_center/message_center.h" #include "ui/message_center/message_center_observer.h" +#include "ui/message_center/message_center_types.h" +#include "ui/message_center/notification_blocker.h" namespace message_center { class NotificationDelegate; class MessageCenterImpl; namespace internal { +struct NotificationQueueItem; class PopupTimersController; // A class that manages timeout behavior for notification popups. One instance @@ -129,16 +133,18 @@ class MESSAGE_CENTER_EXPORT PopupTimersController } // namespace internal // The default implementation of MessageCenter. -class MessageCenterImpl : public MessageCenter { +class MessageCenterImpl : public MessageCenter, + public NotificationBlocker::Observer { public: MessageCenterImpl(); virtual ~MessageCenterImpl(); // MessageCenter overrides: - virtual void SetDelegate(Delegate* delegate) OVERRIDE; virtual void AddObserver(MessageCenterObserver* observer) OVERRIDE; virtual void RemoveObserver(MessageCenterObserver* observer) OVERRIDE; - virtual void SetMessageCenterVisible(bool visible) OVERRIDE; + virtual void AddNotificationBlocker(NotificationBlocker* blocker) OVERRIDE; + virtual void RemoveNotificationBlocker(NotificationBlocker* blocker) OVERRIDE; + virtual void SetVisibility(Visibility visible) OVERRIDE; virtual bool IsMessageCenterVisible() OVERRIDE; virtual size_t NotificationCount() const OVERRIDE; virtual size_t UnreadNotificationCount() const OVERRIDE; @@ -161,9 +167,8 @@ class MessageCenterImpl : public MessageCenter { virtual void SetNotificationButtonIcon(const std::string& notification_id, int button_index, const gfx::Image& image) OVERRIDE; - virtual void DisableNotificationsByExtension(const std::string& id) OVERRIDE; - virtual void DisableNotificationsByUrl(const std::string& id) OVERRIDE; - virtual void ShowNotificationSettings(const std::string& id) OVERRIDE; + virtual void DisableNotificationsByNotifier( + const NotifierId& notifier_id) OVERRIDE; virtual void ExpandNotification(const std::string& id) OVERRIDE; virtual void ClickOnNotification(const std::string& id) OVERRIDE; virtual void ClickOnNotificationButton(const std::string& id, @@ -180,6 +185,9 @@ class MessageCenterImpl : public MessageCenter { virtual void RestartPopupTimers() OVERRIDE; virtual void PausePopupTimers() OVERRIDE; + // NotificationBlocker::Observer overrides: + virtual void OnBlockingStateChanged() OVERRIDE; + protected: virtual void DisableTimersForTest() OVERRIDE; @@ -187,8 +195,13 @@ class MessageCenterImpl : public MessageCenter { scoped_ptr<NotificationList> notification_list_; ObserverList<MessageCenterObserver> observer_list_; scoped_ptr<internal::PopupTimersController> popup_timers_controller_; - Delegate* delegate_; + scoped_ptr<base::OneShotTimer<MessageCenterImpl> > quiet_mode_timer_; NotifierSettingsProvider* settings_provider_; + std::vector<NotificationBlocker*> blockers_; + + // queue for the notifications to delay the addition/updates when the message + // center is visible. + std::list<internal::NotificationQueueItem> notification_queue_; DISALLOW_COPY_AND_ASSIGN(MessageCenterImpl); }; diff --git a/chromium/ui/message_center/message_center_impl_unittest.cc b/chromium/ui/message_center/message_center_impl_unittest.cc index a7c08a8aeb5..fb6969064a8 100644 --- a/chromium/ui/message_center/message_center_impl_unittest.cc +++ b/chromium/ui/message_center/message_center_impl_unittest.cc @@ -9,7 +9,12 @@ #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/layout.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/size.h" #include "ui/message_center/message_center.h" +#include "ui/message_center/message_center_types.h" +#include "ui/message_center/notification_blocker.h" #include "ui/message_center/notification_types.h" namespace message_center { @@ -39,6 +44,20 @@ class MessageCenterImplTest : public testing::Test, base::RunLoop* run_loop() const { return run_loop_.get(); } base::Closure closure() const { return closure_; } + Notification* CreateNotification(const std::string& id) { + RichNotificationData optional_fields; + optional_fields.buttons.push_back(ButtonInfo(UTF8ToUTF16("foo"))); + optional_fields.buttons.push_back(ButtonInfo(UTF8ToUTF16("foo"))); + return new Notification(NOTIFICATION_TYPE_SIMPLE, + id, + UTF8ToUTF16("title"), + UTF8ToUTF16(id), + gfx::Image() /* icon */, + base::string16() /* display_source */, + NotifierId(NotifierId::APPLICATION, "app1"), + optional_fields, + NULL); + } private: MessageCenter* message_center_; scoped_ptr<base::MessageLoop> loop_; @@ -48,6 +67,65 @@ class MessageCenterImplTest : public testing::Test, DISALLOW_COPY_AND_ASSIGN(MessageCenterImplTest); }; +class ToggledNotificationBlocker : public NotificationBlocker { + public: + explicit ToggledNotificationBlocker(MessageCenter* message_center) + : NotificationBlocker(message_center), + notifications_enabled_(true) {} + virtual ~ToggledNotificationBlocker() {} + + void SetNotificationsEnabled(bool enabled) { + if (notifications_enabled_ != enabled) { + notifications_enabled_ = enabled; + FOR_EACH_OBSERVER( + NotificationBlocker::Observer, observers(), OnBlockingStateChanged()); + } + } + + // NotificationBlocker overrides: + virtual bool ShouldShowNotificationAsPopup( + const message_center::NotifierId& notifier_id) const OVERRIDE { + return notifications_enabled_; + } + + private: + bool notifications_enabled_; + + DISALLOW_COPY_AND_ASSIGN(ToggledNotificationBlocker); +}; + +class PopupNotificationBlocker : public ToggledNotificationBlocker { + public: + PopupNotificationBlocker(MessageCenter* message_center, + const NotifierId& allowed_notifier) + : ToggledNotificationBlocker(message_center), + allowed_notifier_(allowed_notifier) {} + virtual ~PopupNotificationBlocker() {} + + // NotificationBlocker overrides: + virtual bool ShouldShowNotificationAsPopup( + const NotifierId& notifier_id) const OVERRIDE { + return (notifier_id == allowed_notifier_) || + ToggledNotificationBlocker::ShouldShowNotificationAsPopup(notifier_id); + } + + private: + NotifierId allowed_notifier_; + + DISALLOW_COPY_AND_ASSIGN(PopupNotificationBlocker); +}; + +bool PopupNotificationsContain( + const NotificationList::PopupNotifications& popups, + const std::string& id) { + for (NotificationList::PopupNotifications::const_iterator iter = + popups.begin(); iter != popups.end(); ++iter) { + if ((*iter)->id() == id) + return true; + } + return false; +} + } // namespace namespace internal { @@ -205,6 +283,271 @@ TEST_F(MessageCenterImplTest, PopupTimersControllerResetTimer) { EXPECT_TRUE(popup_timers_controller->timer_finished()); } -} // namespace internal +TEST_F(MessageCenterImplTest, NotificationBlocker) { + NotifierId notifier_id(NotifierId::APPLICATION, "app1"); + // Multiple blockers to verify the case that one blocker blocks but another + // doesn't. + ToggledNotificationBlocker blocker1(message_center()); + ToggledNotificationBlocker blocker2(message_center()); + + message_center()->AddNotification(scoped_ptr<Notification>(new Notification( + NOTIFICATION_TYPE_SIMPLE, + "id1", + UTF8ToUTF16("title"), + UTF8ToUTF16("message"), + gfx::Image() /* icon */, + base::string16() /* display_source */, + notifier_id, + RichNotificationData(), + NULL))); + message_center()->AddNotification(scoped_ptr<Notification>(new Notification( + NOTIFICATION_TYPE_SIMPLE, + "id2", + UTF8ToUTF16("title"), + UTF8ToUTF16("message"), + gfx::Image() /* icon */, + base::string16() /* display_source */, + notifier_id, + RichNotificationData(), + NULL))); + EXPECT_EQ(2u, message_center()->GetPopupNotifications().size()); + EXPECT_EQ(2u, message_center()->GetNotifications().size()); + + // Block all notifications. All popups are gone and message center should be + // hidden. + blocker1.SetNotificationsEnabled(false); + EXPECT_TRUE(message_center()->GetPopupNotifications().empty()); + EXPECT_EQ(2u, message_center()->GetNotifications().size()); + + // Updates |blocker2| state, which doesn't affect the global state. + blocker2.SetNotificationsEnabled(false); + EXPECT_TRUE(message_center()->GetPopupNotifications().empty()); + EXPECT_EQ(2u, message_center()->GetNotifications().size()); + + blocker2.SetNotificationsEnabled(true); + EXPECT_TRUE(message_center()->GetPopupNotifications().empty()); + EXPECT_EQ(2u, message_center()->GetNotifications().size()); + + // If |blocker2| blocks, then unblocking blocker1 doesn't change the global + // state. + blocker2.SetNotificationsEnabled(false); + blocker1.SetNotificationsEnabled(true); + EXPECT_TRUE(message_center()->GetPopupNotifications().empty()); + EXPECT_EQ(2u, message_center()->GetNotifications().size()); + + // Unblock both blockers, which recovers the global state, but the popups + // aren't shown. + blocker2.SetNotificationsEnabled(true); + EXPECT_TRUE(message_center()->GetPopupNotifications().empty()); + EXPECT_EQ(2u, message_center()->GetNotifications().size()); +} + +TEST_F(MessageCenterImplTest, NotificationsDuringBlocked) { + NotifierId notifier_id(NotifierId::APPLICATION, "app1"); + ToggledNotificationBlocker blocker(message_center()); + + message_center()->AddNotification(scoped_ptr<Notification>(new Notification( + NOTIFICATION_TYPE_SIMPLE, + "id1", + UTF8ToUTF16("title"), + UTF8ToUTF16("message"), + gfx::Image() /* icon */, + base::string16() /* display_source */, + notifier_id, + RichNotificationData(), + NULL))); + EXPECT_EQ(1u, message_center()->GetPopupNotifications().size()); + EXPECT_EQ(1u, message_center()->GetNotifications().size()); + + // Create a notification during blocked. Still no popups. + blocker.SetNotificationsEnabled(false); + message_center()->AddNotification(scoped_ptr<Notification>(new Notification( + NOTIFICATION_TYPE_SIMPLE, + "id2", + UTF8ToUTF16("title"), + UTF8ToUTF16("message"), + gfx::Image() /* icon */, + base::string16() /* display_source */, + notifier_id, + RichNotificationData(), + NULL))); + EXPECT_TRUE(message_center()->GetPopupNotifications().empty()); + EXPECT_EQ(2u, message_center()->GetNotifications().size()); + + // Unblock notifications, the id1 should appear as a popup. + blocker.SetNotificationsEnabled(true); + NotificationList::PopupNotifications popups = + message_center()->GetPopupNotifications(); + EXPECT_EQ(1u, popups.size()); + EXPECT_TRUE(PopupNotificationsContain(popups, "id2")); + EXPECT_EQ(2u, message_center()->GetNotifications().size()); +} + +// Similar to other blocker cases but this test case allows |notifier_id2| even +// in blocked. +TEST_F(MessageCenterImplTest, NotificationBlockerAllowsPopups) { + NotifierId notifier_id1(NotifierId::APPLICATION, "app1"); + NotifierId notifier_id2(NotifierId::APPLICATION, "app2"); + PopupNotificationBlocker blocker(message_center(), notifier_id2); + + message_center()->AddNotification(scoped_ptr<Notification>(new Notification( + NOTIFICATION_TYPE_SIMPLE, + "id1", + UTF8ToUTF16("title"), + UTF8ToUTF16("message"), + gfx::Image() /* icon */, + base::string16() /* display_source */, + notifier_id1, + RichNotificationData(), + NULL))); + message_center()->AddNotification(scoped_ptr<Notification>(new Notification( + NOTIFICATION_TYPE_SIMPLE, + "id2", + UTF8ToUTF16("title"), + UTF8ToUTF16("message"), + gfx::Image() /* icon */, + base::string16() /* display_source */, + notifier_id2, + RichNotificationData(), + NULL))); + + // "id1" is closed but "id2" is still visible as a popup. + blocker.SetNotificationsEnabled(false); + NotificationList::PopupNotifications popups = + message_center()->GetPopupNotifications(); + EXPECT_EQ(1u, popups.size()); + EXPECT_TRUE(PopupNotificationsContain(popups, "id2")); + EXPECT_EQ(2u, message_center()->GetNotifications().size()); + + message_center()->AddNotification(scoped_ptr<Notification>(new Notification( + NOTIFICATION_TYPE_SIMPLE, + "id3", + UTF8ToUTF16("title"), + UTF8ToUTF16("message"), + gfx::Image() /* icon */, + base::string16() /* display_source */, + notifier_id1, + RichNotificationData(), + NULL))); + message_center()->AddNotification(scoped_ptr<Notification>(new Notification( + NOTIFICATION_TYPE_SIMPLE, + "id4", + UTF8ToUTF16("title"), + UTF8ToUTF16("message"), + gfx::Image() /* icon */, + base::string16() /* display_source */, + notifier_id2, + RichNotificationData(), + NULL))); + popups = message_center()->GetPopupNotifications(); + EXPECT_EQ(2u, popups.size()); + EXPECT_TRUE(PopupNotificationsContain(popups, "id2")); + EXPECT_TRUE(PopupNotificationsContain(popups, "id4")); + EXPECT_EQ(4u, message_center()->GetNotifications().size()); + + blocker.SetNotificationsEnabled(true); + popups = message_center()->GetPopupNotifications(); + EXPECT_EQ(3u, popups.size()); + EXPECT_TRUE(PopupNotificationsContain(popups, "id2")); + EXPECT_TRUE(PopupNotificationsContain(popups, "id3")); + EXPECT_TRUE(PopupNotificationsContain(popups, "id4")); + EXPECT_EQ(4u, message_center()->GetNotifications().size()); +} + +TEST_F(MessageCenterImplTest, QueueUpdatesWithCenterVisible) { + std::string id("id1"); + std::string id2("id2"); + NotifierId notifier_id1(NotifierId::APPLICATION, "app1"); + + scoped_ptr<Notification> notification(new Notification( + NOTIFICATION_TYPE_SIMPLE, + id, + UTF8ToUTF16("title"), + UTF8ToUTF16("message"), + gfx::Image() /* icon */, + base::string16() /* display_source */, + notifier_id1, + RichNotificationData(), + NULL)); + + message_center()->AddNotification(notification.Pass()); + notification.reset(new Notification( + NOTIFICATION_TYPE_MULTIPLE, + id2, + UTF8ToUTF16("title"), + UTF8ToUTF16("message"), + gfx::Image() /* icon */, + base::string16() /* display_source */, + notifier_id1, + RichNotificationData(), + NULL)); + message_center()->UpdateNotification(id, notification.Pass()); + EXPECT_TRUE(message_center()->HasNotification(id2)); + EXPECT_FALSE(message_center()->HasNotification(id)); + message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER); + notification.reset(new Notification( + NOTIFICATION_TYPE_MULTIPLE, + id, + UTF8ToUTF16("title"), + UTF8ToUTF16("message"), + gfx::Image() /* icon */, + base::string16() /* display_source */, + notifier_id1, + RichNotificationData(), + NULL)); + message_center()->UpdateNotification(id2, notification.Pass()); + EXPECT_TRUE(message_center()->HasNotification(id2)); + EXPECT_FALSE(message_center()->HasNotification(id)); + message_center()->SetVisibility(VISIBILITY_TRANSIENT); + EXPECT_FALSE(message_center()->HasNotification(id2)); + EXPECT_TRUE(message_center()->HasNotification(id)); +} + +TEST_F(MessageCenterImplTest, QueuedDirectUpdates) { + std::string id("id1"); + std::string id2("id2"); + NotifierId notifier_id1(NotifierId::APPLICATION, "app1"); + + gfx::Size original_size(0, 0); + // Open the message center to prevent adding notifications + message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER); + + // Create new notification to be added to the queue; images all have the same + // original size. + scoped_ptr<Notification> notification(CreateNotification(id)); + + // Double-check that sizes all match. + EXPECT_EQ(original_size, notification->icon().Size()); + message_center()->AddNotification(notification.Pass()); + + // The notification should be in the queue. + EXPECT_FALSE(message_center()->HasNotification(id)); + + // Now try setting the icon to a different size. + gfx::Size new_size(16, 16); + EXPECT_NE(original_size, new_size); + + gfx::Canvas canvas(new_size, ui::SCALE_FACTOR_100P, true); + canvas.DrawColor(SK_ColorBLUE); + gfx::Image testImage(gfx::Image(gfx::ImageSkia(canvas.ExtractImageRep()))); + message_center()->SetNotificationIcon(id, testImage); + message_center()->SetNotificationButtonIcon(id, 0, testImage); + message_center()->SetNotificationButtonIcon(id, 1, testImage); + + // The notification should be in the queue. + EXPECT_FALSE(message_center()->HasNotification(id)); + + // Close the message center; then the update should have propagated. + message_center()->SetVisibility(VISIBILITY_TRANSIENT); + // The notification should no longer be in the queue. + EXPECT_TRUE(message_center()->HasNotification(id)); + + Notification* mc_notification = + *(message_center()->GetNotifications().begin()); + + EXPECT_EQ(new_size, mc_notification->icon().Size()); +} + +} // namespace internal } // namespace message_center diff --git a/chromium/ui/message_center/message_center_observer.h b/chromium/ui/message_center/message_center_observer.h index 8a52792731f..b300db57127 100644 --- a/chromium/ui/message_center/message_center_observer.h +++ b/chromium/ui/message_center/message_center_observer.h @@ -8,6 +8,7 @@ #include <string> #include "ui/message_center/message_center_export.h" +#include "ui/message_center/message_center_types.h" namespace message_center { @@ -42,9 +43,12 @@ class MESSAGE_CENTER_EXPORT MessageCenterObserver { // displayed. virtual void OnNotificationDisplayed(const std::string& notification_id) {} - // Called when the notification list is no longer being displayed as a - // notification center. - virtual void OnNotificationCenterClosed() {} + // Called when the notification center is shown or hidden. + virtual void OnCenterVisibilityChanged(Visibility visibility) {} + + // Called whenever the quiet mode changes as a result of user action or when + // quiet mode expires. + virtual void OnQuietModeChanged(bool in_quiet_mode) {} }; } // namespace message_center diff --git a/chromium/ui/message_center/message_center_style.cc b/chromium/ui/message_center/message_center_style.cc index 0289a96c7f2..a9036bad48a 100644 --- a/chromium/ui/message_center/message_center_style.cc +++ b/chromium/ui/message_center/message_center_style.cc @@ -4,6 +4,8 @@ #include "ui/message_center/message_center_style.h" +#include <algorithm> + namespace message_center { // Exported values ///////////////////////////////////////////////////////////// @@ -42,8 +44,8 @@ const int kMessageLineHeight = 18; // Colors. const SkColor kNotificationBackgroundColor = SkColorSetRGB(255, 255, 255); const SkColor kLegacyIconBackgroundColor = SkColorSetRGB(0xf5, 0xf5, 0xf5); -const SkColor kRegularTextColor = SkColorSetRGB(34, 34, 34); -const SkColor kDimTextColor = SkColorSetRGB(102, 102, 102); +const SkColor kRegularTextColor = SkColorSetRGB(0x33, 0x33, 0x33); +const SkColor kDimTextColor = SkColorSetRGB(0x7f, 0x7f, 0x7f); const SkColor kFocusBorderColor = SkColorSetRGB(64, 128, 250); // Limits. diff --git a/chromium/ui/message_center/message_center_style.h b/chromium/ui/message_center/message_center_style.h index 12353633751..29f9f75175c 100644 --- a/chromium/ui/message_center/message_center_style.h +++ b/chromium/ui/message_center/message_center_style.h @@ -43,10 +43,10 @@ extern const int kIconBottomPadding; // Minimum non-zero V space between icon // and frame. // Text sizes. -extern const int kTitleFontSize; // For title only. -extern const int kTitleLineHeight; // In DIPs. -extern const int kMessageFontSize; // For everything but title. -extern const int kMessageLineHeight; // In DIPs. +extern const int kTitleFontSize; // For title only. +extern const int kTitleLineHeight; // In DIPs. +extern const int kMessageFontSize; // For everything but title. +extern const int kMessageLineHeight; // In DIPs. // Colors. extern const SkColor kNotificationBackgroundColor; // Background of the card. @@ -54,7 +54,7 @@ extern const SkColor kLegacyIconBackgroundColor; // Used behind icons smaller. // than the icon view. extern const SkColor kRegularTextColor; // Title, message, ... extern const SkColor kDimTextColor; -extern const SkColor kFocusBorderColor; // The focus border. +extern const SkColor kFocusBorderColor; // The focus border. // Limits. @@ -91,6 +91,7 @@ const SkColor kProgressBarSliceColor = SkColorSetRGB(120, 120, 120); const int kTitleLineLimit = 3; const int kMessageCollapsedLineLimit = 3; const int kMessageExpandedLineLimit = 7; +const int kContextMessageLineLimit = 1; // Around notifications //////////////////////////////////////////////////////// diff --git a/chromium/ui/message_center/message_center_tray.cc b/chromium/ui/message_center/message_center_tray.cc index 7a1fee8d261..f5bf22e3cae 100644 --- a/chromium/ui/message_center/message_center_tray.cc +++ b/chromium/ui/message_center/message_center_tray.cc @@ -10,16 +10,9 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/message_center/message_center.h" #include "ui/message_center/message_center_tray_delegate.h" +#include "ui/message_center/message_center_types.h" namespace message_center { -namespace { - -// Menu commands -const int kToggleQuietMode = 0; -const int kEnableQuietModeHour = 1; -const int kEnableQuietModeDay = 2; - -} MessageCenterTray::MessageCenterTray( MessageCenterTrayDelegate* delegate, @@ -39,10 +32,11 @@ bool MessageCenterTray::ShowMessageCenterBubble() { if (message_center_visible_) return true; - HidePopupBubble(); + HidePopupBubbleInternal(); message_center_visible_ = delegate_->ShowMessageCenter(); - message_center_->SetMessageCenterVisible(message_center_visible_); + message_center_->SetVisibility(message_center::VISIBILITY_MESSAGE_CENTER); + NotifyMessageCenterTrayChanged(); return message_center_visible_; } @@ -58,11 +52,16 @@ void MessageCenterTray::MarkMessageCenterHidden() { if (!message_center_visible_) return; message_center_visible_ = false; - message_center_->SetMessageCenterVisible(false); + // Some notifications (like system ones) should appear as popups again // after the message center is closed. - if (message_center_->HasPopupNotifications()) + if (message_center_->HasPopupNotifications()) { ShowPopupBubble(); + return; + } + + message_center_->SetVisibility(message_center::VISIBILITY_TRANSIENT); + NotifyMessageCenterTrayChanged(); } @@ -86,37 +85,35 @@ void MessageCenterTray::ShowPopupBubble() { return; popups_visible_ = delegate_->ShowPopups(); + NotifyMessageCenterTrayChanged(); } bool MessageCenterTray::HidePopupBubble() { if (!popups_visible_) return false; - - delegate_->HidePopups(); - popups_visible_ = false; + HidePopupBubbleInternal(); NotifyMessageCenterTrayChanged(); return true; } +void MessageCenterTray::HidePopupBubbleInternal() { + if (!popups_visible_) + return; + + delegate_->HidePopups(); + popups_visible_ = false; +} + void MessageCenterTray::ShowNotifierSettingsBubble() { if (popups_visible_) - HidePopupBubble(); + HidePopupBubbleInternal(); message_center_visible_ = delegate_->ShowNotifierSettings(); -} + message_center_->SetVisibility(message_center::VISIBILITY_SETTINGS); -ui::MenuModel* MessageCenterTray::CreateQuietModeMenu() { - ui::SimpleMenuModel* menu = new ui::SimpleMenuModel(this); - - menu->AddCheckItem(kToggleQuietMode, - l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_QUIET_MODE)); - menu->AddItem(kEnableQuietModeHour, - l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_QUIET_MODE_1HOUR)); - menu->AddItem(kEnableQuietModeDay, - l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_QUIET_MODE_1DAY)); - return menu; + NotifyMessageCenterTrayChanged(); } void MessageCenterTray::OnNotificationAdded( @@ -153,47 +150,19 @@ void MessageCenterTray::OnNotificationDisplayed( NotifyMessageCenterTrayChanged(); } -void MessageCenterTray::OnMessageCenterChanged() { - if (message_center_visible_) { - if (message_center_->NotificationCount() == 0) - HideMessageCenterBubble(); - } - - if (popups_visible_ && !message_center_->HasPopupNotifications()) - HidePopupBubble(); - else if (message_center_->HasPopupNotifications()) - ShowPopupBubble(); - +void MessageCenterTray::OnQuietModeChanged(bool in_quiet_mode) { NotifyMessageCenterTrayChanged(); } -bool MessageCenterTray::IsCommandIdChecked(int command_id) const { - if (command_id != kToggleQuietMode) - return false; - return message_center()->IsQuietMode(); -} - -bool MessageCenterTray::IsCommandIdEnabled(int command_id) const { - return true; -} +void MessageCenterTray::OnMessageCenterChanged() { + if (message_center_visible_ && message_center_->NotificationCount() == 0) + HideMessageCenterBubble(); -bool MessageCenterTray::GetAcceleratorForCommandId( - int command_id, - ui::Accelerator* accelerator) { - return false; -} + if (popups_visible_ && !message_center_->HasPopupNotifications()) + HidePopupBubbleInternal(); + else if (!popups_visible_ && message_center_->HasPopupNotifications()) + ShowPopupBubble(); -void MessageCenterTray::ExecuteCommand(int command_id, int event_flags) { - if (command_id == kToggleQuietMode) { - bool in_quiet_mode = message_center()->IsQuietMode(); - message_center()->SetQuietMode(!in_quiet_mode); - NotifyMessageCenterTrayChanged(); - return; - } - base::TimeDelta expires_in = command_id == kEnableQuietModeDay ? - base::TimeDelta::FromDays(1): - base::TimeDelta::FromHours(1); - message_center()->EnterQuietModeWithExpire(expires_in); NotifyMessageCenterTrayChanged(); } diff --git a/chromium/ui/message_center/message_center_tray.h b/chromium/ui/message_center/message_center_tray.h index 03b86e9391e..444bb2f4ecb 100644 --- a/chromium/ui/message_center/message_center_tray.h +++ b/chromium/ui/message_center/message_center_tray.h @@ -6,7 +6,6 @@ #define UI_MESSAGE_CENTER_MESSAGE_CENTER_TRAY_H_ #include "base/observer_list.h" -#include "ui/base/models/simple_menu_model.h" #include "ui/message_center/message_center_export.h" #include "ui/message_center/message_center_observer.h" #include "ui/message_center/message_center_tray_delegate.h" @@ -25,9 +24,7 @@ MessageCenterTrayDelegate* CreateMessageCenterTray(); // Class that observes a MessageCenter. Manages the popup and message center // bubbles. Tells the MessageCenterTrayHost when the tray is changed, as well // as when bubbles are shown and hidden. -class MESSAGE_CENTER_EXPORT MessageCenterTray - : public MessageCenterObserver, - public ui::SimpleMenuModel::Delegate { +class MESSAGE_CENTER_EXPORT MessageCenterTray : public MessageCenterObserver { public: MessageCenterTray(MessageCenterTrayDelegate* delegate, message_center::MessageCenter* message_center); @@ -57,10 +54,6 @@ class MESSAGE_CENTER_EXPORT MessageCenterTray // Toggles the visibility of the settings view in the message center bubble. void ShowNotifierSettingsBubble(); - // Creates the menu model for quiet mode and returns it. The caller must - // take the ownership of the return value. - ui::MenuModel* CreateQuietModeMenu(); - bool message_center_visible() { return message_center_visible_; } bool popups_visible() { return popups_visible_; } MessageCenterTrayDelegate* delegate() { return delegate_; } @@ -82,18 +75,12 @@ class MESSAGE_CENTER_EXPORT MessageCenterTray int button_index) OVERRIDE; virtual void OnNotificationDisplayed( const std::string& notification_id) OVERRIDE; - - // Overridden from SimpleMenuModel::Delegate. - virtual bool IsCommandIdChecked(int command_id) const OVERRIDE; - virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE; - virtual bool GetAcceleratorForCommandId( - int command_id, - ui::Accelerator* accelerator) OVERRIDE; - virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE; + virtual void OnQuietModeChanged(bool in_quiet_mode) OVERRIDE; private: void OnMessageCenterChanged(); void NotifyMessageCenterTrayChanged(); + void HidePopupBubbleInternal(); // |message_center_| is a weak pointer that must live longer than // MessageCenterTray. diff --git a/chromium/ui/message_center/message_center_tray_unittest.cc b/chromium/ui/message_center/message_center_tray_unittest.cc index 108cee7aa29..6a68b2b989f 100644 --- a/chromium/ui/message_center/message_center_tray_unittest.cc +++ b/chromium/ui/message_center/message_center_tray_unittest.cc @@ -71,7 +71,7 @@ class MessageCenterTrayTest : public testing::Test { ASCIIToUTF16("Notification message body."), gfx::Image(), ASCIIToUTF16("www.test.org"), - "" /* extension id */, + NotifierId(), message_center::RichNotificationData(), NULL /* delegate */)); message_center_->AddNotification(notification.Pass()); @@ -147,6 +147,7 @@ TEST_F(MessageCenterTrayTest, MessageCenterClosesPopups) { ASSERT_FALSE(message_center_tray_->popups_visible()); ASSERT_TRUE(message_center_tray_->message_center_visible()); + // The notification is queued if it's added when message center is visible. AddNotification("MessageCenterClosesPopups2"); message_center_tray_->ShowPopupBubble(); @@ -156,6 +157,12 @@ TEST_F(MessageCenterTrayTest, MessageCenterClosesPopups) { message_center_tray_->HideMessageCenterBubble(); + // The queued notification appears as a popup. + ASSERT_TRUE(message_center_tray_->popups_visible()); + ASSERT_FALSE(message_center_tray_->message_center_visible()); + + message_center_tray_->ShowMessageCenterBubble(); + message_center_tray_->HideMessageCenterBubble(); ASSERT_FALSE(message_center_tray_->popups_visible()); ASSERT_FALSE(message_center_tray_->message_center_visible()); } @@ -171,7 +178,7 @@ TEST_F(MessageCenterTrayTest, MessageCenterReopenPopupsForSystemPriority) { ASCIIToUTF16("Notification message body."), gfx::Image(), ASCIIToUTF16("www.test.org"), - "" /* extension id */, + NotifierId(), message_center::RichNotificationData(), NULL /* delegate */)); notification->SetSystemPriority(); diff --git a/chromium/ui/message_center/message_center_types.h b/chromium/ui/message_center/message_center_types.h new file mode 100644 index 00000000000..4cfe68e6fad --- /dev/null +++ b/chromium/ui/message_center/message_center_types.h @@ -0,0 +1,21 @@ +// 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. + +#ifndef UI_MESSAGE_CENTER_MESSAGE_CENTER_TYPES_H_ +#define UI_MESSAGE_CENTER_MESSAGE_CENTER_TYPES_H_ + +namespace message_center { + +enum Visibility { + // When nothing or just toast popups are being displayed. + VISIBILITY_TRANSIENT = 0, + // When the message center view is being displayed. + VISIBILITY_MESSAGE_CENTER, + // When the settings view is being displayed. + VISIBILITY_SETTINGS +}; + +} // namespace message_center + +#endif // UI_MESSAGE_CENTER_MESSAGE_CENTER_TYPES_H_ diff --git a/chromium/ui/message_center/notification.cc b/chromium/ui/message_center/notification.cc index 5d3014e8156..e17667c91c7 100644 --- a/chromium/ui/message_center/notification.cc +++ b/chromium/ui/message_center/notification.cc @@ -5,6 +5,7 @@ #include "ui/message_center/notification.h" #include "base/logging.h" +#include "ui/message_center/notification_delegate.h" #include "ui/message_center/notification_types.h" namespace { @@ -27,17 +28,21 @@ RichNotificationData::RichNotificationData() : priority(DEFAULT_PRIORITY), never_timeout(false), timestamp(base::Time::Now()), - progress(0) {} + progress(0), + should_make_spoken_feedback_for_popup_updates(true) {} RichNotificationData::RichNotificationData(const RichNotificationData& other) : priority(other.priority), never_timeout(other.never_timeout), timestamp(other.timestamp), expanded_message(other.expanded_message), + context_message(other.context_message), image(other.image), items(other.items), progress(other.progress), - buttons(other.buttons) {} + buttons(other.buttons), + should_make_spoken_feedback_for_popup_updates( + other.should_make_spoken_feedback_for_popup_updates) {} RichNotificationData::~RichNotificationData() {} @@ -47,7 +52,7 @@ Notification::Notification(NotificationType type, const string16& message, const gfx::Image& icon, const string16& display_source, - const std::string& extension_id, + const NotifierId& notifier_id, const RichNotificationData& optional_fields, NotificationDelegate* delegate) : type_(type), @@ -56,7 +61,7 @@ Notification::Notification(NotificationType type, message_(message), icon_(icon), display_source_(display_source), - extension_id_(extension_id), + notifier_id_(notifier_id), serial_number_(g_next_serial_number_++), optional_fields_(optional_fields), shown_as_popup_(false), @@ -71,7 +76,7 @@ Notification::Notification(const Notification& other) message_(other.message_), icon_(other.icon_), display_source_(other.display_source_), - extension_id_(other.extension_id_), + notifier_id_(other.notifier_id_), serial_number_(other.serial_number_), optional_fields_(other.optional_fields_), shown_as_popup_(other.shown_as_popup_), @@ -86,7 +91,7 @@ Notification& Notification::operator=(const Notification& other) { message_ = other.message_; icon_ = other.icon_; display_source_ = other.display_source_; - extension_id_ = other.extension_id_; + notifier_id_ = other.notifier_id_; serial_number_ = other.serial_number_; optional_fields_ = other.optional_fields_; shown_as_popup_ = other.shown_as_popup_; @@ -119,4 +124,27 @@ void Notification::SetSystemPriority() { optional_fields_.never_timeout = true; } +// static +scoped_ptr<Notification> Notification::CreateSystemNotification( + const std::string& notification_id, + const base::string16& title, + const base::string16& message, + const gfx::Image& icon, + int system_component_id, + const base::Closure& click_callback) { + scoped_ptr<Notification> notification( + new Notification( + NOTIFICATION_TYPE_SIMPLE, + notification_id, + title, + message, + icon, + base::string16() /* display_source */, + NotifierId(system_component_id), + RichNotificationData(), + new HandleNotificationClickedDelegate(click_callback))); + notification->SetSystemPriority(); + return notification.Pass(); +} + } // namespace message_center diff --git a/chromium/ui/message_center/notification.h b/chromium/ui/message_center/notification.h index bda6900fb0c..f61d6d60d60 100644 --- a/chromium/ui/message_center/notification.h +++ b/chromium/ui/message_center/notification.h @@ -15,6 +15,7 @@ #include "ui/message_center/message_center_export.h" #include "ui/message_center/notification_delegate.h" #include "ui/message_center/notification_types.h" +#include "ui/message_center/notifier_settings.h" namespace message_center { @@ -42,10 +43,12 @@ class MESSAGE_CENTER_EXPORT RichNotificationData { bool never_timeout; base::Time timestamp; string16 expanded_message; + string16 context_message; gfx::Image image; std::vector<NotificationItem> items; int progress; std::vector<ButtonInfo> buttons; + bool should_make_spoken_feedback_for_popup_updates; }; class MESSAGE_CENTER_EXPORT Notification { @@ -56,7 +59,7 @@ class MESSAGE_CENTER_EXPORT Notification { const string16& message, const gfx::Image& icon, const string16& display_source, - const std::string& extension_id, + const NotifierId& notifier_id, const RichNotificationData& optional_fields, NotificationDelegate* delegate); @@ -81,10 +84,8 @@ class MESSAGE_CENTER_EXPORT Notification { // A display string for the source of the notification. const string16& display_source() const { return display_source_; } - const std::string& extension_id() const { return extension_id_; } - void set_extension_id(const std::string& extension_id) { - extension_id_ = extension_id; - } + + const NotifierId& notifier_id() const { return notifier_id_; } // Begin unpacked values from optional_fields. int priority() const { return optional_fields_.priority; } @@ -102,6 +103,13 @@ class MESSAGE_CENTER_EXPORT Notification { optional_fields_.expanded_message = expanded_message; } + const string16& context_message() const { + return optional_fields_.context_message; + } + void set_context_message(const string16& context_message) { + optional_fields_.context_message = context_message; + } + const std::vector<NotificationItem>& items() const { return optional_fields_.items; } @@ -167,6 +175,16 @@ class MESSAGE_CENTER_EXPORT Notification { void ButtonClick(int index) const { delegate()->ButtonClick(index); } void Close(bool by_user) const { delegate()->Close(by_user); } + // Helper method to create a simple System notification. |click_callback| + // will be invoked when the notification is clicked. + static scoped_ptr<Notification> CreateSystemNotification( + const std::string& notification_id, + const base::string16& title, + const base::string16& message, + const gfx::Image& icon, + int system_component_id, + const base::Closure& click_callback); + protected: // The type of notification we'd like displayed. NotificationType type_; @@ -183,7 +201,7 @@ class MESSAGE_CENTER_EXPORT Notification { string16 display_source_; private: - std::string extension_id_; + NotifierId notifier_id_; unsigned serial_number_; RichNotificationData optional_fields_; bool shown_as_popup_; // True if this has been shown as a popup. diff --git a/chromium/ui/message_center/notification_blocker.cc b/chromium/ui/message_center/notification_blocker.cc new file mode 100644 index 00000000000..6d6c5d3ce16 --- /dev/null +++ b/chromium/ui/message_center/notification_blocker.cc @@ -0,0 +1,31 @@ +// 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 "ui/message_center/notification_blocker.h" + +#include "ui/message_center/message_center.h" + +namespace message_center { + +NotificationBlocker::NotificationBlocker(MessageCenter* message_center) + : message_center_(message_center) { + if (message_center_) + message_center_->AddNotificationBlocker(this); +} + +NotificationBlocker::~NotificationBlocker() { + if (message_center_) + message_center_->RemoveNotificationBlocker(this); +} + +void NotificationBlocker::AddObserver(NotificationBlocker::Observer* observer) { + observers_.AddObserver(observer); +} + +void NotificationBlocker::RemoveObserver( + NotificationBlocker::Observer* observer) { + observers_.RemoveObserver(observer); +} + +} // namespace message_center diff --git a/chromium/ui/message_center/notification_blocker.h b/chromium/ui/message_center/notification_blocker.h new file mode 100644 index 00000000000..437f0eb1238 --- /dev/null +++ b/chromium/ui/message_center/notification_blocker.h @@ -0,0 +1,51 @@ +// 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. + +#ifndef UI_MESSAGE_CENTER_NOTIFICATION_BLOCKER_H_ +#define UI_MESSAGE_CENTER_NOTIFICATION_BLOCKER_H_ + +#include "base/observer_list.h" +#include "ui/message_center/message_center_export.h" +#include "ui/message_center/notifier_settings.h" + +namespace message_center { +class MessageCenter; + +// NotificationBlocker manages the availability of notifications based on the +// current system status. Each NotificationBlocker implementation covers a +// single state such as screen lock or fullscreen. +class MESSAGE_CENTER_EXPORT NotificationBlocker { + public: + class Observer { + public: + virtual void OnBlockingStateChanged() = 0; + }; + + explicit NotificationBlocker(MessageCenter* message_center); + virtual ~NotificationBlocker(); + + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + // Checks the current state and updates the availability. + virtual void CheckState() {} + + // Returns true when notifications from |notifier_id| should be shown as + // popups on screen. If it's false, those notifications should be queued. + // When a blocker starts returning false for a notification which is already + // shown as a popup, the notification should be closed as a popup immediately. + virtual bool ShouldShowNotificationAsPopup( + const NotifierId& notifier_id) const = 0; + + protected: + ObserverList<Observer>& observers() { return observers_; } + + private: + ObserverList<Observer> observers_; + MessageCenter* message_center_; // weak +}; + +} // namespace message_center + +#endif // UI_MESSAGE_CENTER_NOTIFICATION_BLOCKER_H_ diff --git a/chromium/ui/message_center/notification_list.cc b/chromium/ui/message_center/notification_list.cc index d0527922b8c..bed592c7cb2 100644 --- a/chromium/ui/message_center/notification_list.cc +++ b/chromium/ui/message_center/notification_list.cc @@ -11,10 +11,25 @@ #include "base/values.h" #include "ui/message_center/message_center_style.h" #include "ui/message_center/notification.h" +#include "ui/message_center/notification_blocker.h" #include "ui/message_center/notification_types.h" namespace message_center { +namespace { + +bool ShouldShowNotificationAsPopup( + const NotifierId& notifier_id, + const std::vector<NotificationBlocker*>& blockers) { + for (size_t i = 0; i < blockers.size(); ++i) { + if (!blockers[i]->ShouldShowNotificationAsPopup(notifier_id)) + return false; + } + return true; +} + +} // namespace + bool ComparePriorityTimestampSerial::operator()(Notification* n1, Notification* n2) { if (n1->priority() > n2->priority()) // Higher pri go first. @@ -114,33 +129,12 @@ void NotificationList::RemoveAllNotifications() { unread_count_ = 0; } -NotificationList::Notifications NotificationList::GetNotificationsBySource( - const std::string& id) { - Notifications notifications; - Notifications::iterator source_iter = GetNotification(id); - if (source_iter == notifications_.end()) - return notifications; - - string16 display_source = (*source_iter)->display_source(); - for (Notifications::iterator iter = notifications_.begin(); - iter != notifications_.end(); ++iter) { - if ((*iter)->display_source() == display_source) - notifications.insert(*iter); - } - return notifications; -} - -NotificationList::Notifications NotificationList::GetNotificationsByExtension( - const std::string& id) { +NotificationList::Notifications NotificationList::GetNotificationsByNotifierId( + const NotifierId& notifier_id) { Notifications notifications; - Notifications::iterator source_iter = GetNotification(id); - if (source_iter == notifications_.end()) - return notifications; - - std::string extension_id = (*source_iter)->extension_id(); for (Notifications::iterator iter = notifications_.begin(); iter != notifications_.end(); ++iter) { - if ((*iter)->extension_id() == extension_id) + if ((*iter)->notifier_id() == notifier_id) notifications.insert(*iter); } return notifications; @@ -178,18 +172,32 @@ bool NotificationList::HasNotification(const std::string& id) { return GetNotification(id) != notifications_.end(); } -bool NotificationList::HasPopupNotifications() { +bool NotificationList::HasNotificationOfType(const std::string& id, + const NotificationType type) { + Notifications::iterator iter = GetNotification(id); + if (iter == notifications_.end()) + return false; + + return (*iter)->type() == type; +} + +bool NotificationList::HasPopupNotifications( + const std::vector<NotificationBlocker*>& blockers) { for (Notifications::iterator iter = notifications_.begin(); iter != notifications_.end(); ++iter) { if ((*iter)->priority() < DEFAULT_PRIORITY) break; + if (!ShouldShowNotificationAsPopup((*iter)->notifier_id(), blockers)) + continue; if (!(*iter)->shown_as_popup()) return true; } return false; } -NotificationList::PopupNotifications NotificationList::GetPopupNotifications() { +NotificationList::PopupNotifications NotificationList::GetPopupNotifications( + const std::vector<NotificationBlocker*>& blockers, + std::list<std::string>* blocked_ids) { PopupNotifications result; size_t default_priority_popup_count = 0; @@ -203,6 +211,12 @@ NotificationList::PopupNotifications NotificationList::GetPopupNotifications() { if ((*iter)->priority() < DEFAULT_PRIORITY) continue; + if (!ShouldShowNotificationAsPopup((*iter)->notifier_id(), blockers)) { + if (blocked_ids) + blocked_ids->push_back((*iter)->id()); + continue; + } + // Checking limits. No limits for HIGH/MAX priority. DEFAULT priority // will return at most kMaxVisiblePopupNotifications entries. If the // popup entries are more, older entries are used. see crbug.com/165768 @@ -216,26 +230,6 @@ NotificationList::PopupNotifications NotificationList::GetPopupNotifications() { return result; } -Notification* NotificationList::GetPopup(const std::string& id) { - PopupNotifications popups = GetPopupNotifications(); - for (PopupNotifications::iterator iter = popups.begin(); iter != popups.end(); - ++iter) { - if ((*iter)->id() == id) - return *iter; - } - - return NULL; -} - -void NotificationList::MarkPopupsAsShown(int priority) { - PopupNotifications popups = GetPopupNotifications(); - for (PopupNotifications::iterator iter = popups.begin(); - iter != popups.end(); ++iter) { - if ((*iter)->priority() == priority) - (*iter)->set_shown_as_popup(true); - } -} - void NotificationList::MarkSinglePopupAsShown( const std::string& id, bool mark_notification_as_read) { Notifications::iterator iter = GetNotification(id); @@ -285,21 +279,13 @@ NotificationDelegate* NotificationList::GetNotificationDelegate( } void NotificationList::SetQuietMode(bool quiet_mode) { - SetQuietModeInternal(quiet_mode); - quiet_mode_timer_.reset(); -} - -void NotificationList::EnterQuietModeWithExpire( - const base::TimeDelta& expires_in) { - if (quiet_mode_timer_.get()) { - // Note that the capital Reset() is the method to restart the timer, not - // scoped_ptr::reset(). - quiet_mode_timer_->Reset(); - } else { - SetQuietModeInternal(true); - quiet_mode_timer_.reset(new base::OneShotTimer<NotificationList>); - quiet_mode_timer_->Start(FROM_HERE, expires_in, base::Bind( - &NotificationList::SetQuietMode, base::Unretained(this), false)); + quiet_mode_ = quiet_mode; + if (quiet_mode_) { + for (Notifications::iterator iter = notifications_.begin(); + iter != notifications_.end(); + ++iter) { + (*iter)->set_shown_as_popup(true); + } } } @@ -311,19 +297,8 @@ size_t NotificationList::NotificationCount() const { return notifications_.size(); } -void NotificationList::SetQuietModeInternal(bool quiet_mode) { - quiet_mode_ = quiet_mode; - if (quiet_mode_) { - for (Notifications::iterator iter = notifications_.begin(); - iter != notifications_.end(); - ++iter) { - (*iter)->set_shown_as_popup(true); - } - } -} - -NotificationList::Notifications::iterator - NotificationList::GetNotification(const std::string& id) { +NotificationList::Notifications::iterator NotificationList::GetNotification( + const std::string& id) { for (Notifications::iterator iter = notifications_.begin(); iter != notifications_.end(); ++iter) { if ((*iter)->id() == id) diff --git a/chromium/ui/message_center/notification_list.h b/chromium/ui/message_center/notification_list.h index ce24498d7e9..69eb9fcf589 100644 --- a/chromium/ui/message_center/notification_list.h +++ b/chromium/ui/message_center/notification_list.h @@ -5,6 +5,7 @@ #ifndef UI_MESSAGE_CENTER_NOTIFICATION_LIST_H_ #define UI_MESSAGE_CENTER_NOTIFICATION_LIST_H_ +#include <list> #include <set> #include <string> @@ -23,6 +24,7 @@ class DictionaryValue; namespace message_center { +class NotificationBlocker; class NotificationDelegate; namespace test { @@ -67,8 +69,7 @@ class MESSAGE_CENTER_EXPORT NotificationList { void RemoveAllNotifications(); - Notifications GetNotificationsBySource(const std::string& id); - Notifications GetNotificationsByExtension(const std::string& id); + Notifications GetNotificationsByNotifierId(const NotifierId& notifier_id); // Returns true if the notification exists and was updated. bool SetNotificationIcon(const std::string& notification_id, @@ -83,21 +84,27 @@ class MESSAGE_CENTER_EXPORT NotificationList { int button_index, const gfx::Image& image); + // Returns true if |id| matches a notification in the list. bool HasNotification(const std::string& id); + // Returns true if |id| matches a notification in the list and that + // notification's type matches the given type. + bool HasNotificationOfType(const std::string& id, + const NotificationType type); + // Returns false if the first notification has been shown as a popup (which // means that all notifications have been shown). - bool HasPopupNotifications(); + bool HasPopupNotifications(const std::vector<NotificationBlocker*>& blockers); // Returns the recent notifications of the priority higher then LOW, // that have not been shown as a popup. kMaxVisiblePopupNotifications are // used to limit the number of notifications for the DEFAULT priority. - // The returned list is sorted by timestamp, newer first. - PopupNotifications GetPopupNotifications(); - Notification* GetPopup(const std::string& id); - - // Marks the popups for the |priority| as shown. - void MarkPopupsAsShown(int priority); + // It also stores the list of notification ids which is blocked by |blockers| + // to |blocked_ids|. |blocked_ids| can be NULL if the caller doesn't care + // which notifications are blocked. + PopupNotifications GetPopupNotifications( + const std::vector<NotificationBlocker*>& blockers, + std::list<std::string>* blocked_ids); // Marks a specific popup item as shown. Set |mark_notification_as_read| to // true in case marking the notification as read too. @@ -114,8 +121,7 @@ class MESSAGE_CENTER_EXPORT NotificationList { bool quiet_mode() const { return quiet_mode_; } - // Sets the current quiet mode status to |quiet_mode|. The new status is not - // expired. + // Sets the current quiet mode status to |quiet_mode|. void SetQuietMode(bool quiet_mode); // Sets the current quiet mode to true. The quiet mode will expire in the @@ -139,14 +145,10 @@ class MESSAGE_CENTER_EXPORT NotificationList { void PushNotification(scoped_ptr<Notification> notification); - // Sets the current quiet mode status to |quiet_mode|. - void SetQuietModeInternal(bool quiet_mode); - Notifications notifications_; bool message_center_visible_; size_t unread_count_; bool quiet_mode_; - scoped_ptr<base::OneShotTimer<NotificationList> > quiet_mode_timer_; DISALLOW_COPY_AND_ASSIGN(NotificationList); }; diff --git a/chromium/ui/message_center/notification_list_unittest.cc b/chromium/ui/message_center/notification_list_unittest.cc index cdd6ad42832..4e6f5d1ee49 100644 --- a/chromium/ui/message_center/notification_list_unittest.cc +++ b/chromium/ui/message_center/notification_list_unittest.cc @@ -11,7 +11,9 @@ #include "base/values.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/message_center/message_center_style.h" +#include "ui/message_center/notification_blocker.h" #include "ui/message_center/notification_types.h" +#include "ui/message_center/notifier_settings.h" namespace message_center { namespace test { @@ -40,7 +42,7 @@ class NotificationListTest : public testing::Test { UTF8ToUTF16(base::StringPrintf(kMessageFormat, counter_)), gfx::Image(), UTF8ToUTF16(kDisplaySource), - kExtensionId, + NotifierId(NotifierId::APPLICATION, kExtensionId), optional_fields, NULL)); notification_list_->AddNotification(notification.Pass()); @@ -59,8 +61,13 @@ class NotificationListTest : public testing::Test { return AddNotification(optional); } + NotificationList::PopupNotifications GetPopups() { + return notification_list()->GetPopupNotifications( + std::vector<NotificationBlocker*>(), NULL); + } + size_t GetPopupCounts() { - return notification_list()->GetPopupNotifications().size(); + return GetPopups().size(); } Notification* GetNotification(const std::string& id) { @@ -112,14 +119,16 @@ TEST_F(NotificationListTest, Basic) { EXPECT_EQ(2u, notification_list()->NotificationCount()); EXPECT_EQ(2u, notification_list()->unread_count()); - EXPECT_TRUE(notification_list()->HasPopupNotifications()); + EXPECT_TRUE(notification_list()->HasPopupNotifications( + std::vector<NotificationBlocker*>())); EXPECT_TRUE(notification_list()->HasNotification(id0)); EXPECT_TRUE(notification_list()->HasNotification(id1)); EXPECT_FALSE(notification_list()->HasNotification(id1 + "foo")); EXPECT_EQ(2u, GetPopupCounts()); - notification_list()->MarkPopupsAsShown(0); + notification_list()->MarkSinglePopupAsShown(id0, true); + notification_list()->MarkSinglePopupAsShown(id1, true); EXPECT_EQ(2u, notification_list()->NotificationCount()); EXPECT_EQ(0u, GetPopupCounts()); @@ -172,7 +181,7 @@ TEST_F(NotificationListTest, UpdateNotification) { UTF8ToUTF16("newbody"), gfx::Image(), UTF8ToUTF16(kDisplaySource), - kExtensionId, + NotifierId(NotifierId::APPLICATION, kExtensionId), message_center::RichNotificationData(), NULL)); notification_list()->UpdateNotificationMessage(id0, notification.Pass()); @@ -184,7 +193,11 @@ TEST_F(NotificationListTest, UpdateNotification) { EXPECT_EQ(UTF8ToUTF16("newbody"), (*notifications.begin())->message()); } -TEST_F(NotificationListTest, GetNotificationsBySourceOrExtensions) { +TEST_F(NotificationListTest, GetNotificationsByNotifierId) { + NotifierId id0(NotifierId::APPLICATION, "ext0"); + NotifierId id1(NotifierId::APPLICATION, "ext1"); + NotifierId id2(GURL("http://example.com")); + NotifierId id3(0); scoped_ptr<Notification> notification( new Notification(message_center::NOTIFICATION_TYPE_SIMPLE, "id0", @@ -192,7 +205,7 @@ TEST_F(NotificationListTest, GetNotificationsBySourceOrExtensions) { UTF8ToUTF16("message0"), gfx::Image(), UTF8ToUTF16("source0"), - "ext0", + id0, message_center::RichNotificationData(), NULL)); notification_list()->AddNotification(notification.Pass()); @@ -202,7 +215,7 @@ TEST_F(NotificationListTest, GetNotificationsBySourceOrExtensions) { UTF8ToUTF16("message1"), gfx::Image(), UTF8ToUTF16("source0"), - "ext0", + id0, message_center::RichNotificationData(), NULL)); notification_list()->AddNotification(notification.Pass()); @@ -212,7 +225,7 @@ TEST_F(NotificationListTest, GetNotificationsBySourceOrExtensions) { UTF8ToUTF16("message1"), gfx::Image(), UTF8ToUTF16("source1"), - "ext0", + id0, message_center::RichNotificationData(), NULL)); notification_list()->AddNotification(notification.Pass()); @@ -222,24 +235,63 @@ TEST_F(NotificationListTest, GetNotificationsBySourceOrExtensions) { UTF8ToUTF16("message1"), gfx::Image(), UTF8ToUTF16("source2"), - "ext1", + id1, + message_center::RichNotificationData(), + NULL)); + notification_list()->AddNotification(notification.Pass()); + notification.reset(new Notification(message_center::NOTIFICATION_TYPE_SIMPLE, + "id4", + UTF8ToUTF16("title1"), + UTF8ToUTF16("message1"), + gfx::Image(), + UTF8ToUTF16("source2"), + id2, + message_center::RichNotificationData(), + NULL)); + notification_list()->AddNotification(notification.Pass()); + notification.reset(new Notification(message_center::NOTIFICATION_TYPE_SIMPLE, + "id5", + UTF8ToUTF16("title1"), + UTF8ToUTF16("message1"), + gfx::Image(), + UTF8ToUTF16("source2"), + id3, message_center::RichNotificationData(), NULL)); notification_list()->AddNotification(notification.Pass()); - NotificationList::Notifications by_source = - notification_list()->GetNotificationsBySource("id0"); - EXPECT_TRUE(IsInNotifications(by_source, "id0")); - EXPECT_TRUE(IsInNotifications(by_source, "id1")); - EXPECT_FALSE(IsInNotifications(by_source, "id2")); - EXPECT_FALSE(IsInNotifications(by_source, "id3")); - - NotificationList::Notifications by_extension = - notification_list()->GetNotificationsByExtension("id0"); - EXPECT_TRUE(IsInNotifications(by_extension, "id0")); - EXPECT_TRUE(IsInNotifications(by_extension, "id1")); - EXPECT_TRUE(IsInNotifications(by_extension, "id2")); - EXPECT_FALSE(IsInNotifications(by_extension, "id3")); + NotificationList::Notifications by_notifier_id = + notification_list()->GetNotificationsByNotifierId(id0); + EXPECT_TRUE(IsInNotifications(by_notifier_id, "id0")); + EXPECT_TRUE(IsInNotifications(by_notifier_id, "id1")); + EXPECT_TRUE(IsInNotifications(by_notifier_id, "id2")); + EXPECT_FALSE(IsInNotifications(by_notifier_id, "id3")); + EXPECT_FALSE(IsInNotifications(by_notifier_id, "id4")); + EXPECT_FALSE(IsInNotifications(by_notifier_id, "id5")); + + by_notifier_id = notification_list()->GetNotificationsByNotifierId(id1); + EXPECT_FALSE(IsInNotifications(by_notifier_id, "id0")); + EXPECT_FALSE(IsInNotifications(by_notifier_id, "id1")); + EXPECT_FALSE(IsInNotifications(by_notifier_id, "id2")); + EXPECT_TRUE(IsInNotifications(by_notifier_id, "id3")); + EXPECT_FALSE(IsInNotifications(by_notifier_id, "id4")); + EXPECT_FALSE(IsInNotifications(by_notifier_id, "id5")); + + by_notifier_id = notification_list()->GetNotificationsByNotifierId(id2); + EXPECT_FALSE(IsInNotifications(by_notifier_id, "id0")); + EXPECT_FALSE(IsInNotifications(by_notifier_id, "id1")); + EXPECT_FALSE(IsInNotifications(by_notifier_id, "id2")); + EXPECT_FALSE(IsInNotifications(by_notifier_id, "id3")); + EXPECT_TRUE(IsInNotifications(by_notifier_id, "id4")); + EXPECT_FALSE(IsInNotifications(by_notifier_id, "id5")); + + by_notifier_id = notification_list()->GetNotificationsByNotifierId(id3); + EXPECT_FALSE(IsInNotifications(by_notifier_id, "id0")); + EXPECT_FALSE(IsInNotifications(by_notifier_id, "id1")); + EXPECT_FALSE(IsInNotifications(by_notifier_id, "id2")); + EXPECT_FALSE(IsInNotifications(by_notifier_id, "id3")); + EXPECT_FALSE(IsInNotifications(by_notifier_id, "id4")); + EXPECT_TRUE(IsInNotifications(by_notifier_id, "id5")); } TEST_F(NotificationListTest, OldPopupShouldNotBeHidden) { @@ -247,8 +299,7 @@ TEST_F(NotificationListTest, OldPopupShouldNotBeHidden) { for (size_t i = 0; i <= kMaxVisiblePopupNotifications; i++) ids.push_back(AddNotification()); - NotificationList::PopupNotifications popups = - notification_list()->GetPopupNotifications(); + NotificationList::PopupNotifications popups = GetPopups(); // The popup should contain the oldest kMaxVisiblePopupNotifications. Newer // one should come earlier in the popup list. It means, the last element // of |popups| should be the firstly added one, and so on. @@ -259,9 +310,12 @@ TEST_F(NotificationListTest, OldPopupShouldNotBeHidden) { EXPECT_EQ(ids[i], (*iter)->id()) << i; } - notification_list()->MarkPopupsAsShown(message_center::DEFAULT_PRIORITY); + for (NotificationList::PopupNotifications::const_iterator iter = + popups.begin(); iter != popups.end(); ++iter) { + notification_list()->MarkSinglePopupAsShown((*iter)->id(), false); + } popups.clear(); - popups = notification_list()->GetPopupNotifications(); + popups = GetPopups(); EXPECT_EQ(1u, popups.size()); EXPECT_EQ(ids[ids.size() - 1], (*popups.begin())->id()); } @@ -355,7 +409,7 @@ TEST_F(NotificationListTest, PriorityPromotion) { UTF8ToUTF16("newbody"), gfx::Image(), UTF8ToUTF16(kDisplaySource), - kExtensionId, + NotifierId(NotifierId::APPLICATION, kExtensionId), optional, NULL)); notification_list()->UpdateNotificationMessage(id0, notification.Pass()); @@ -386,7 +440,7 @@ TEST_F(NotificationListTest, PriorityPromotionWithPopups) { UTF8ToUTF16("newbody"), gfx::Image(), UTF8ToUTF16(kDisplaySource), - kExtensionId, + NotifierId(NotifierId::APPLICATION, kExtensionId), priority, NULL)); notification_list()->UpdateNotificationMessage(id0, notification.Pass()); @@ -401,7 +455,8 @@ TEST_F(NotificationListTest, PriorityPromotionWithPopups) { UTF8ToUTF16("newbody2"), gfx::Image(), UTF8ToUTF16(kDisplaySource), - kExtensionId, + NotifierId(NotifierId::APPLICATION, + kExtensionId), priority, NULL)); notification_list()->UpdateNotificationMessage(id0, notification.Pass()); @@ -415,7 +470,8 @@ TEST_F(NotificationListTest, PriorityPromotionWithPopups) { UTF8ToUTF16("newbody"), gfx::Image(), UTF8ToUTF16(kDisplaySource), - kExtensionId, + NotifierId(NotifierId::APPLICATION, + kExtensionId), priority, NULL)); notification_list()->UpdateNotificationMessage(id1, notification.Pass()); @@ -431,7 +487,8 @@ TEST_F(NotificationListTest, PriorityPromotionWithPopups) { UTF8ToUTF16("newbody2"), gfx::Image(), UTF8ToUTF16(kDisplaySource), - kExtensionId, + NotifierId(NotifierId::APPLICATION, + kExtensionId), priority, NULL)); notification_list()->UpdateNotificationMessage(id1, notification.Pass()); @@ -447,7 +504,8 @@ TEST_F(NotificationListTest, PriorityPromotionWithPopups) { UTF8ToUTF16("newbody3"), gfx::Image(), UTF8ToUTF16(kDisplaySource), - kExtensionId, + NotifierId(NotifierId::APPLICATION, + kExtensionId), priority, NULL)); notification_list()->UpdateNotificationMessage(id1, notification.Pass()); @@ -473,8 +531,7 @@ TEST_F(NotificationListTest, NotificationOrderAndPriority) { { // Popups: latest comes first. - NotificationList::PopupNotifications popups = - notification_list()->GetPopupNotifications(); + NotificationList::PopupNotifications popups = GetPopups(); EXPECT_EQ(3u, popups.size()); NotificationList::PopupNotifications::const_iterator iter = popups.begin(); EXPECT_EQ(default_id, (*iter)->id()); @@ -514,8 +571,7 @@ TEST_F(NotificationListTest, MarkSinglePopupAsShown) { EXPECT_EQ(3u, notification_list()->NotificationCount()); EXPECT_EQ(1u, notification_list()->unread_count()); EXPECT_EQ(1u, GetPopupCounts()); - NotificationList::PopupNotifications popups = - notification_list()->GetPopupNotifications(); + NotificationList::PopupNotifications popups = GetPopups(); EXPECT_EQ(id1, (*popups.begin())->id()); // The notifications in the NotificationCenter are unaffected by popups shown. @@ -527,39 +583,6 @@ TEST_F(NotificationListTest, MarkSinglePopupAsShown) { EXPECT_EQ(id2, (*iter)->id()); iter++; EXPECT_EQ(id1, (*iter)->id()); - - // Trickier scenario. - notification_list()->MarkPopupsAsShown(message_center::DEFAULT_PRIORITY); - std::string id4 = AddNotification(); - std::string id5 = AddNotification(); - std::string id6 = AddNotification(); - notification_list()->MarkSinglePopupAsShown(id5, true); - - { - popups.clear(); - popups = notification_list()->GetPopupNotifications(); - EXPECT_EQ(2u, popups.size()); - NotificationList::PopupNotifications::const_iterator iter = popups.begin(); - EXPECT_EQ(id6, (*iter)->id()); - iter++; - EXPECT_EQ(id4, (*iter)->id()); - } - - notifications.clear(); - notifications = notification_list()->GetNotifications(); - EXPECT_EQ(6u, notifications.size()); - iter = notifications.begin(); - EXPECT_EQ(id6, (*iter)->id()); - iter++; - EXPECT_EQ(id5, (*iter)->id()); - iter++; - EXPECT_EQ(id4, (*iter)->id()); - iter++; - EXPECT_EQ(id3, (*iter)->id()); - iter++; - EXPECT_EQ(id2, (*iter)->id()); - iter++; - EXPECT_EQ(id1, (*iter)->id()); } TEST_F(NotificationListTest, UpdateAfterMarkedAsShown) { @@ -588,7 +611,7 @@ TEST_F(NotificationListTest, UpdateAfterMarkedAsShown) { UTF8ToUTF16("newbody"), gfx::Image(), UTF8ToUTF16(kDisplaySource), - kExtensionId, + NotifierId(NotifierId::APPLICATION, kExtensionId), message_center::RichNotificationData(), NULL)); notification_list()->UpdateNotificationMessage(id1, notification.Pass()); @@ -634,12 +657,38 @@ TEST_F(NotificationListTest, UnreadCountNoNegative) { UTF8ToUTF16("updated"), gfx::Image(), base::string16(), - std::string(), + NotifierId(), RichNotificationData(), NULL)); notification_list()->AddNotification(updated_notification.Pass()); EXPECT_EQ(1u, notification_list()->unread_count()); } +TEST_F(NotificationListTest, TestHasNotificationOfType) { + std::string id = AddNotification(); + + EXPECT_TRUE(notification_list()->HasNotificationOfType( + id, message_center::NOTIFICATION_TYPE_SIMPLE)); + EXPECT_FALSE(notification_list()->HasNotificationOfType( + id, message_center::NOTIFICATION_TYPE_PROGRESS)); + + scoped_ptr<Notification> updated_notification(new Notification( + message_center::NOTIFICATION_TYPE_PROGRESS, + id, + UTF8ToUTF16("updated"), + UTF8ToUTF16("updated"), + gfx::Image(), + base::string16(), + NotifierId(), + RichNotificationData(), + NULL)); + notification_list()->AddNotification(updated_notification.Pass()); + + EXPECT_FALSE(notification_list()->HasNotificationOfType( + id, message_center::NOTIFICATION_TYPE_SIMPLE)); + EXPECT_TRUE(notification_list()->HasNotificationOfType( + id, message_center::NOTIFICATION_TYPE_PROGRESS)); +} + } // namespace test } // namespace message_center diff --git a/chromium/ui/message_center/notifier_settings.cc b/chromium/ui/message_center/notifier_settings.cc index 4355b9459fe..861e65b651f 100644 --- a/chromium/ui/message_center/notifier_settings.cc +++ b/chromium/ui/message_center/notifier_settings.cc @@ -11,15 +11,26 @@ NotifierId::NotifierId(NotifierType type, const std::string& id) : type(type), id(id), - system_component_type(NONE) { + system_component_type(-1) { DCHECK(type == APPLICATION || type == SYNCED_NOTIFICATION_SERVICE); + DCHECK(!id.empty()); } NotifierId::NotifierId(const GURL& url) - : type(WEB_PAGE), url(url), system_component_type(NONE) {} + : type(WEB_PAGE), + url(url), + system_component_type(-1) {} -NotifierId::NotifierId(SystemComponentNotifierType system_component_type) - : type(SYSTEM_COMPONENT), system_component_type(system_component_type) {} +NotifierId::NotifierId(int type) + : type(SYSTEM_COMPONENT), + system_component_type(type) { + DCHECK_LE(0, system_component_type); +} + +NotifierId::NotifierId() + : type(SYSTEM_COMPONENT), + system_component_type(-1) { +} bool NotifierId::operator==(const NotifierId& other) const { if (type != other.type) @@ -58,23 +69,4 @@ NotifierGroup::NotifierGroup(const gfx::Image& icon, NotifierGroup::~NotifierGroup() {} -std::string ToString(NotifierId::SystemComponentNotifierType type) { - switch (type) { - case NotifierId::SCREENSHOT: - return "screenshot"; - default: - NOTREACHED(); - return ""; - } -} - -NotifierId::SystemComponentNotifierType -ParseSystemComponentName(const std::string& name) { - if (name == "screenshot") { - return NotifierId::SCREENSHOT; - } else { - NOTREACHED(); - return NotifierId::NONE; - } -} } // namespace message_center diff --git a/chromium/ui/message_center/notifier_settings.h b/chromium/ui/message_center/notifier_settings.h index b8771a399cc..6188599e20a 100644 --- a/chromium/ui/message_center/notifier_settings.h +++ b/chromium/ui/message_center/notifier_settings.h @@ -33,19 +33,17 @@ struct MESSAGE_CENTER_EXPORT NotifierId { SYNCED_NOTIFICATION_SERVICE, }; - enum SystemComponentNotifierType { - NONE, - SCREENSHOT, - }; - // Constructor for APPLICATION and SYNCED_NOTIFICATION_SERVICE type. NotifierId(NotifierType type, const std::string& id); // Constructor for WEB_PAGE type. explicit NotifierId(const GURL& url); - // Constructor for SYSTEM_COMPONENT type. - explicit NotifierId(SystemComponentNotifierType type); + // Constructor for system component types. The type should be positive. + explicit NotifierId(int type); + + // The default constructor which doesn't specify the notifier. Used for tests. + NotifierId(); bool operator==(const NotifierId& other) const; @@ -58,8 +56,9 @@ struct MESSAGE_CENTER_EXPORT NotifierId { // The URL pattern of the notifer. GURL url; - // The type of system component notifier. - SystemComponentNotifierType system_component_type; + // The type of system component notifier, usually used in ash. -1 if it's not + // the system component. See also: ash/system/system_notifier.h + int system_component_type; }; // The struct to hold the information of notifiers. The information will be @@ -108,11 +107,6 @@ struct MESSAGE_CENTER_EXPORT NotifierGroup { DISALLOW_COPY_AND_ASSIGN(NotifierGroup); }; -MESSAGE_CENTER_EXPORT std::string ToString( - NotifierId::SystemComponentNotifierType type); -MESSAGE_CENTER_EXPORT NotifierId::SystemComponentNotifierType - ParseSystemComponentName(const std::string& name); - // An observer class implemented by the view of the NotifierSettings to get // notified when the controller has changed data. class MESSAGE_CENTER_EXPORT NotifierSettingsObserver { diff --git a/chromium/ui/message_center/views/bounded_label.cc b/chromium/ui/message_center/views/bounded_label.cc index 6752795390e..9c6f4df5840 100644 --- a/chromium/ui/message_center/views/bounded_label.cc +++ b/chromium/ui/message_center/views/bounded_label.cc @@ -8,8 +8,8 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "ui/base/text/text_elider.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/text_elider.h" #include "ui/views/controls/label.h" namespace { @@ -143,18 +143,18 @@ std::vector<string16> InnerBoundedLabel::GetWrappedText(int width, int lines) { // Wrap, using INT_MAX for -1 widths that indicate no wrapping. std::vector<string16> wrapped; - ui::ElideRectangleText(text(), font(), - (width < 0) ? std::numeric_limits<int>::max() : width, - height, ui::WRAP_LONG_WORDS, &wrapped); + gfx::ElideRectangleText(text(), font_list(), + (width < 0) ? std::numeric_limits<int>::max() : width, + height, gfx::WRAP_LONG_WORDS, &wrapped); // Elide if necessary. if (lines > 0 && wrapped.size() > static_cast<unsigned int>(lines)) { // Add an ellipsis to the last line. If this ellipsis makes the last line - // too wide, that line will be further elided by the ui::ElideText below, + // too wide, that line will be further elided by the gfx::ElideText below, // so for example "ABC" could become "ABC..." and then "AB...". - string16 last = wrapped[lines - 1] + UTF8ToUTF16(ui::kEllipsis); + string16 last = wrapped[lines - 1] + UTF8ToUTF16(gfx::kEllipsis); if (width > 0 && font().GetStringWidth(last) > width) - last = ui::ElideText(last, font(), width, ui::ELIDE_AT_END); + last = gfx::ElideText(last, font(), width, gfx::ELIDE_AT_END); wrapped.resize(lines - 1); wrapped.push_back(last); } @@ -259,10 +259,10 @@ void InnerBoundedLabel::SetCachedSize(std::pair<int, int> width_and_lines, // BoundedLabel /////////////////////////////////////////////////////////// -BoundedLabel::BoundedLabel(const string16& text, gfx::Font font) +BoundedLabel::BoundedLabel(const string16& text, const gfx::FontList& font_list) : line_limit_(-1) { label_.reset(new InnerBoundedLabel(*this)); - label_->SetFont(font); + label_->SetFontList(font_list); label_->SetText(text); } diff --git a/chromium/ui/message_center/views/bounded_label.h b/chromium/ui/message_center/views/bounded_label.h index 6d97c8850cc..d6b2f49a519 100644 --- a/chromium/ui/message_center/views/bounded_label.h +++ b/chromium/ui/message_center/views/bounded_label.h @@ -14,7 +14,7 @@ #include "ui/views/view.h" namespace gfx { -class Font; +class FontList; } namespace message_center { @@ -33,7 +33,7 @@ class BoundedLabelTest; // bounded_label.cc file for details. class MESSAGE_CENTER_EXPORT BoundedLabel : public views::View { public: - BoundedLabel(const string16& text, gfx::Font font); + BoundedLabel(const string16& text, const gfx::FontList& font_list); BoundedLabel(const string16& text); virtual ~BoundedLabel(); diff --git a/chromium/ui/message_center/views/bounded_label_unittest.cc b/chromium/ui/message_center/views/bounded_label_unittest.cc index a73d84bba9e..bdfb0aceeb6 100644 --- a/chromium/ui/message_center/views/bounded_label_unittest.cc +++ b/chromium/ui/message_center/views/bounded_label_unittest.cc @@ -10,7 +10,8 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/font.h" +#include "ui/gfx/font_list.h" +#include "ui/gfx/text_utils.h" #include "ui/views/controls/label.h" namespace message_center { @@ -22,9 +23,10 @@ namespace test { class BoundedLabelTest : public testing::Test { public: BoundedLabelTest() { - digit_pixels_ = font_.GetStringWidth(UTF8ToUTF16("0")); - space_pixels_ = font_.GetStringWidth(UTF8ToUTF16(" ")); - ellipsis_pixels_ = font_.GetStringWidth(UTF8ToUTF16("\xE2\x80\xA6")); + digit_pixels_ = gfx::GetStringWidth(UTF8ToUTF16("0"), font_list_); + space_pixels_ = gfx::GetStringWidth(UTF8ToUTF16(" "), font_list_); + ellipsis_pixels_ = gfx::GetStringWidth(UTF8ToUTF16("\xE2\x80\xA6"), + font_list_); } virtual ~BoundedLabelTest() {} @@ -62,7 +64,7 @@ class BoundedLabelTest : public testing::Test { // Exercise BounderLabel::GetLinesForWidthAndLimit() using the test label. int GetLinesForWidth(int width) { - label_->SetBounds(0, 0, width, font_.GetHeight() * lines_); + label_->SetBounds(0, 0, width, font_list_.GetHeight() * lines_); return label_->GetLinesForWidthAndLimit(width, lines_); } @@ -71,13 +73,14 @@ class BoundedLabelTest : public testing::Test { // test the newly created label using the exercise methods above. BoundedLabelTest& Label(string16 text, int lines) { lines_ = lines; - label_.reset(new BoundedLabel(text, font_)); + label_.reset(new BoundedLabel(text, font_list_)); label_->SetLineLimit(lines_); return *this; } private: - gfx::Font font_; // The default font, which will be used for tests. + // The default font list, which will be used for tests. + gfx::FontList font_list_; int digit_pixels_; int space_pixels_; int ellipsis_pixels_; diff --git a/chromium/ui/message_center/views/message_center_view.cc b/chromium/ui/message_center/views/message_center_view.cc index 95c2cc37669..2acece7402a 100644 --- a/chromium/ui/message_center/views/message_center_view.cc +++ b/chromium/ui/message_center/views/message_center_view.cc @@ -11,15 +11,16 @@ #include "base/message_loop/message_loop.h" #include "base/stl_util.h" #include "grit/ui_strings.h" -#include "ui/base/animation/multi_animation.h" -#include "ui/base/animation/slide_animation.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/animation/multi_animation.h" +#include "ui/gfx/animation/slide_animation.h" #include "ui/gfx/canvas.h" #include "ui/gfx/insets.h" #include "ui/gfx/rect.h" #include "ui/gfx/size.h" #include "ui/message_center/message_center.h" #include "ui/message_center/message_center_style.h" +#include "ui/message_center/message_center_types.h" #include "ui/message_center/views/message_center_button_bar.h" #include "ui/message_center/views/message_view.h" #include "ui/message_center/views/notification_view.h" @@ -415,7 +416,7 @@ void MessageListView::OnBoundsAnimatorProgressed( DCHECK_EQ(animator_.get(), animator); for (std::set<views::View*>::iterator iter = deleted_when_done_.begin(); iter != deleted_when_done_.end(); ++iter) { - const ui::SlideAnimation* animation = animator->GetAnimationForView(*iter); + const gfx::SlideAnimation* animation = animator->GetAnimationForView(*iter); if (animation) (*iter)->layer()->SetOpacity(animation->CurrentValueBetween(1.0, 0.0)); } @@ -683,28 +684,28 @@ void MessageCenterView::SetSettingsVisible(bool visible) { source_height_ = source_view_->GetHeightForWidth(width()); target_height_ = target_view_->GetHeightForWidth(width()); - ui::MultiAnimation::Parts parts; + gfx::MultiAnimation::Parts parts; // First part: slide resize animation. - parts.push_back(ui::MultiAnimation::Part( + parts.push_back(gfx::MultiAnimation::Part( (source_height_ == target_height_) ? 0 : kDefaultAnimationDurationMs, - ui::Tween::EASE_OUT)); + gfx::Tween::EASE_OUT)); // Second part: fade-out the source_view. if (source_view_->layer()) { - parts.push_back(ui::MultiAnimation::Part( - kDefaultAnimationDurationMs, ui::Tween::LINEAR)); + parts.push_back(gfx::MultiAnimation::Part( + kDefaultAnimationDurationMs, gfx::Tween::LINEAR)); } else { - parts.push_back(ui::MultiAnimation::Part()); + parts.push_back(gfx::MultiAnimation::Part()); } // Third part: fade-in the target_view. if (target_view_->layer()) { - parts.push_back(ui::MultiAnimation::Part( - kDefaultAnimationDurationMs, ui::Tween::LINEAR)); + parts.push_back(gfx::MultiAnimation::Part( + kDefaultAnimationDurationMs, gfx::Tween::LINEAR)); target_view_->layer()->SetOpacity(0); target_view_->SetVisible(true); } else { - parts.push_back(ui::MultiAnimation::Part()); + parts.push_back(gfx::MultiAnimation::Part()); } - settings_transition_animation_.reset(new ui::MultiAnimation( + settings_transition_animation_.reset(new gfx::MultiAnimation( parts, base::TimeDelta::FromMicroseconds(1000000 / kDefaultFrameRateHz))); settings_transition_animation_->set_delegate(this); settings_transition_animation_->set_continuous(false); @@ -931,9 +932,14 @@ void MessageCenterView::OnNotificationUpdated(const std::string& id) { } } -void MessageCenterView::AnimationEnded(const ui::Animation* animation) { +void MessageCenterView::AnimationEnded(const gfx::Animation* animation) { DCHECK_EQ(animation, settings_transition_animation_.get()); + Visibility visibility = target_view_ == settings_view_ + ? VISIBILITY_SETTINGS + : VISIBILITY_MESSAGE_CENTER; + message_center_->SetVisibility(visibility); + source_view_->SetVisible(false); target_view_->SetVisible(true); if (source_view_->layer()) @@ -945,7 +951,7 @@ void MessageCenterView::AnimationEnded(const ui::Animation* animation) { Layout(); } -void MessageCenterView::AnimationProgressed(const ui::Animation* animation) { +void MessageCenterView::AnimationProgressed(const gfx::Animation* animation) { DCHECK_EQ(animation, settings_transition_animation_.get()); PreferredSizeChanged(); if (settings_transition_animation_->current_part_index() == 1 && @@ -961,7 +967,7 @@ void MessageCenterView::AnimationProgressed(const ui::Animation* animation) { } } -void MessageCenterView::AnimationCanceled(const ui::Animation* animation) { +void MessageCenterView::AnimationCanceled(const gfx::Animation* animation) { DCHECK_EQ(animation, settings_transition_animation_.get()); AnimationEnded(animation); } diff --git a/chromium/ui/message_center/views/message_center_view.h b/chromium/ui/message_center/views/message_center_view.h index d53910c2734..7e3c8296730 100644 --- a/chromium/ui/message_center/views/message_center_view.h +++ b/chromium/ui/message_center/views/message_center_view.h @@ -7,15 +7,15 @@ #include "ui/views/view.h" -#include "ui/base/animation/animation_delegate.h" +#include "ui/gfx/animation/animation_delegate.h" #include "ui/message_center/message_center_export.h" #include "ui/message_center/message_center_observer.h" #include "ui/message_center/notification_list.h" #include "ui/views/controls/button/button.h" -namespace ui { +namespace gfx { class MultiAnimation; -} // namespace ui +} // namespace gfx namespace views { class Button; @@ -37,7 +37,7 @@ class NotifierSettingsView; class MESSAGE_CENTER_EXPORT MessageCenterView : public views::View, public MessageCenterObserver, - public ui::AnimationDelegate { + public gfx::AnimationDelegate { public: MessageCenterView(MessageCenter* message_center, MessageCenterTray* tray, @@ -73,10 +73,10 @@ class MESSAGE_CENTER_EXPORT MessageCenterView : public views::View, bool by_user) OVERRIDE; virtual void OnNotificationUpdated(const std::string& id) OVERRIDE; - // Overridden from ui::AnimationDelegate: - virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE; - virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; - virtual void AnimationCanceled(const ui::Animation* animation) OVERRIDE; + // Overridden from gfx::AnimationDelegate: + virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE; + virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; + virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE; private: friend class MessageCenterViewTest; @@ -102,7 +102,7 @@ class MESSAGE_CENTER_EXPORT MessageCenterView : public views::View, // Animation managing transition between message center and settings (and vice // versa). - scoped_ptr<ui::MultiAnimation> settings_transition_animation_; + scoped_ptr<gfx::MultiAnimation> settings_transition_animation_; // Helper data to keep track of the transition between settings and // message center views. diff --git a/chromium/ui/message_center/views/message_center_view_unittest.cc b/chromium/ui/message_center/views/message_center_view_unittest.cc index f6e05f4e30f..b9e34a1ebd1 100644 --- a/chromium/ui/message_center/views/message_center_view_unittest.cc +++ b/chromium/ui/message_center/views/message_center_view_unittest.cc @@ -133,7 +133,7 @@ void MessageCenterViewTest::SetUp() { UTF8ToUTF16("message"), gfx::Image(), UTF8ToUTF16("display source"), - std::string("extension id"), + NotifierId(NotifierId::APPLICATION, "extension_id"), message_center::RichNotificationData(), NULL); diff --git a/chromium/ui/message_center/views/message_popup_collection.cc b/chromium/ui/message_center/views/message_popup_collection.cc index 130a8650f6a..5355ad6962b 100644 --- a/chromium/ui/message_center/views/message_popup_collection.cc +++ b/chromium/ui/message_center/views/message_popup_collection.cc @@ -14,8 +14,8 @@ #include "base/time/time.h" #include "base/timer/timer.h" #include "ui/base/accessibility/accessibility_types.h" -#include "ui/base/animation/animation_delegate.h" -#include "ui/base/animation/slide_animation.h" +#include "ui/gfx/animation/animation_delegate.h" +#include "ui/gfx/animation/slide_animation.h" #include "ui/gfx/screen.h" #include "ui/message_center/message_center.h" #include "ui/message_center/message_center_style.h" @@ -150,9 +150,14 @@ void MessagePopupCollection::UpdateWidgets() { toasts_.push_back(toast); gfx::Size preferred_size = toast->GetPreferredSize(); - gfx::Point origin( - GetToastOriginX(gfx::Rect(preferred_size)) + preferred_size.width(), - top_down ? base + view_height : base); + gfx::Point origin(GetToastOriginX(gfx::Rect(preferred_size)), base); + // The toast slides in from the edge of the screen horizontally. + if (alignment_ & POPUP_ALIGNMENT_LEFT) + origin.set_x(origin.x() - preferred_size.width()); + else + origin.set_x(origin.x() + preferred_size.width()); + if (top_down) + origin.set_y(origin.y() + view_height); toast->RevealWithAnimation(origin); // Shift the base line to be a few pixels above the last added toast or (few @@ -358,9 +363,7 @@ void MessagePopupCollection::OnNotificationRemoved( return; target_top_edge_ = (*iter)->bounds().y(); - (*iter)->CloseWithAnimation(true); - if (by_user) { - RepositionWidgetsWithTarget(); + if (by_user && !user_is_closing_toasts_by_clicking_) { // [Re] start a timeout after which the toasts re-position to their // normal locations after tracking the mouse pointer for easy deletion. // This provides a period of time when toasts are easy to remove because @@ -368,11 +371,18 @@ void MessagePopupCollection::OnNotificationRemoved( // pointer. If the user continue to remove the toasts, the delay is reset. // Once user stopped removing the toasts, the toasts re-populate/rearrange // after the specified delay. - if (!user_is_closing_toasts_by_clicking_) { - user_is_closing_toasts_by_clicking_ = true; - IncrementDeferCounter(); - } + user_is_closing_toasts_by_clicking_ = true; + IncrementDeferCounter(); } + + // CloseWithAnimation ultimately causes a call to RemoveToast, which calls + // OnMouseExited. This means that |user_is_closing_toasts_by_clicking_| must + // have been set before this call, otherwise it will remain true even after + // the toast is closed, since the defer timer won't be started. + (*iter)->CloseWithAnimation(true); + + if (by_user) + RepositionWidgetsWithTarget(); } void MessagePopupCollection::OnDeferTimerExpired() { diff --git a/chromium/ui/message_center/views/message_popup_collection_unittest.cc b/chromium/ui/message_center/views/message_popup_collection_unittest.cc index 52299edd6d9..cca2774729e 100644 --- a/chromium/ui/message_center/views/message_popup_collection_unittest.cc +++ b/chromium/ui/message_center/views/message_popup_collection_unittest.cc @@ -10,8 +10,8 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_constants.h" +#include "ui/events/event.h" +#include "ui/events/event_constants.h" #include "ui/gfx/display.h" #include "ui/gfx/rect.h" #include "ui/message_center/fake_message_center.h" @@ -90,7 +90,7 @@ class MessagePopupCollectionTest : public views::ViewsTestBase { UTF8ToUTF16("test message"), gfx::Image(), string16() /* display_source */, - "" /* extension_id */, + NotifierId(), message_center::RichNotificationData(), NULL /* delegate */)); MessageCenter::Get()->AddNotification(notification.Pass()); @@ -377,6 +377,29 @@ TEST_F(MessagePopupCollectionTest, DetectMouseHover) { // TODO(dimich): Test repositioning - both normal one and when user is closing // the toasts. +TEST_F(MessagePopupCollectionTest, DetectMouseHoverWithUserClose) { + std::string id0 = AddNotification(); + std::string id1 = AddNotification(); + WaitForTransitionsDone(); + + views::WidgetDelegateView* toast0 = GetToast(id0); + EXPECT_TRUE(toast0 != NULL); + views::WidgetDelegateView* toast1 = GetToast(id1); + ASSERT_TRUE(toast1 != NULL); + + ui::MouseEvent event(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(), 0); + toast1->OnMouseEntered(event); + static_cast<MessageCenterObserver*>(collection())->OnNotificationRemoved( + id1, true); + + EXPECT_FALSE(MouseInCollection()); + std::string id2 = AddNotification(); + + WaitForTransitionsDone(); + views::WidgetDelegateView* toast2 = GetToast(id2); + EXPECT_TRUE(toast2 != NULL); +} + } // namespace test } // namespace message_center diff --git a/chromium/ui/message_center/views/message_view.cc b/chromium/ui/message_center/views/message_view.cc index 7eb9838e24b..e3199ccdb4b 100644 --- a/chromium/ui/message_center/views/message_view.cc +++ b/chromium/ui/message_center/views/message_view.cc @@ -35,8 +35,7 @@ const int kShadowBlur = 4; // Menu constants const int kTogglePermissionCommand = 0; -const int kToggleExtensionCommand = 1; -const int kShowSettingsCommand = 2; +const int kShowSettingsCommand = 1; // ControlButtons are ImageButtons whose image can be padded within the button. // This allows the creation of buttons like the notification close and expand @@ -170,7 +169,7 @@ class MenuModel : public ui::SimpleMenuModel, message_center::MessageCenterTray* tray, const std::string& notification_id, const string16& display_source, - const std::string& extension_id); + const message_center::NotifierId& notifier_id); virtual ~MenuModel(); // Overridden from ui::SimpleMenuModel::Delegate: @@ -186,6 +185,7 @@ class MenuModel : public ui::SimpleMenuModel, message_center::MessageCenter* message_center_; // Weak reference. message_center::MessageCenterTray* tray_; // Weak reference. std::string notification_id_; + message_center::NotifierId notifier_id_; DISALLOW_COPY_AND_ASSIGN(MenuModel); }; @@ -194,19 +194,16 @@ MenuModel::MenuModel(message_center::MessageCenter* message_center, message_center::MessageCenterTray* tray, const std::string& notification_id, const string16& display_source, - const std::string& extension_id) + const message_center::NotifierId& notifier_id) : ui::SimpleMenuModel(this), message_center_(message_center), tray_(tray), - notification_id_(notification_id) { + notification_id_(notification_id), + notifier_id_(notifier_id) { // Add 'disable notifications' menu item. - if (!extension_id.empty() && !display_source.empty()) { - AddItem(kToggleExtensionCommand, - l10n_util::GetStringFUTF16(IDS_MESSAGE_CENTER_EXTENSIONS_DISABLE, - display_source)); - } else if (!display_source.empty()) { + if (!display_source.empty()) { AddItem(kTogglePermissionCommand, - l10n_util::GetStringFUTF16(IDS_MESSAGE_CENTER_SITE_DISABLE, + l10n_util::GetStringFUTF16(IDS_MESSAGE_CENTER_NOTIFIER_DISABLE, display_source)); } // Add settings menu item. @@ -236,18 +233,13 @@ bool MenuModel::GetAcceleratorForCommandId(int command_id, void MenuModel::ExecuteCommand(int command_id, int event_flags) { switch (command_id) { - case kToggleExtensionCommand: - message_center_->DisableNotificationsByExtension(notification_id_); - break; case kTogglePermissionCommand: - message_center_->DisableNotificationsByUrl(notification_id_); + message_center_->DisableNotificationsByNotifier(notifier_id_); break; case kShowSettingsCommand: // |tray_| may be NULL in tests. if (tray_) tray_->ShowNotifierSettingsBubble(); - else - message_center_->ShowNotificationSettings(notification_id_); break; default: NOTREACHED(); @@ -276,7 +268,7 @@ class MessageViewContextMenuController : public views::ContextMenuController { MessageCenterTray* tray_; // Weak reference. std::string notification_id_; string16 display_source_; - std::string extension_id_; + NotifierId notifier_id_; }; MessageViewContextMenuController::MessageViewContextMenuController( @@ -287,7 +279,7 @@ MessageViewContextMenuController::MessageViewContextMenuController( tray_(tray), notification_id_(notification.id()), display_source_(notification.display_source()), - extension_id_(notification.extension_id()) { + notifier_id_(notification.notifier_id()) { } MessageViewContextMenuController::~MessageViewContextMenuController() { @@ -298,7 +290,7 @@ void MessageViewContextMenuController::ShowContextMenuForView( const gfx::Point& point, ui::MenuSourceType source_type) { MenuModel menu_model(message_center_, tray_, notification_id_, - display_source_, extension_id_); + display_source_, notifier_id_); if (menu_model.GetItemCount() == 0) return; diff --git a/chromium/ui/message_center/views/notification_view.cc b/chromium/ui/message_center/views/notification_view.cc index abfc1efe689..b6e8bcc8d4b 100644 --- a/chromium/ui/message_center/views/notification_view.cc +++ b/chromium/ui/message_center/views/notification_view.cc @@ -10,10 +10,10 @@ #include "grit/ui_resources.h" #include "ui/base/layout.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/base/text/text_elider.h" #include "ui/gfx/canvas.h" #include "ui/gfx/size.h" #include "ui/gfx/skia_util.h" +#include "ui/gfx/text_elider.h" #include "ui/message_center/message_center.h" #include "ui/message_center/message_center_style.h" #include "ui/message_center/message_center_switches.h" @@ -30,6 +30,10 @@ #include "ui/views/layout/fill_layout.h" #include "ui/views/widget/widget.h" +#if defined(USE_AURA) +#include "ui/base/cursor/cursor.h" +#endif + namespace { // Dimensions. @@ -53,12 +57,16 @@ const size_t kTitleCharacterLimit = const size_t kMessageCharacterLimit = message_center::kNotificationWidth * message_center::kMessageExpandedLineLimit / 3; +const size_t kContextMessageCharacterLimit = + message_center::kNotificationWidth * + message_center::kContextMessageLineLimit / 3; // Notification colors. The text background colors below are used only to keep // view::Label from modifying the text color and will not actually be drawn. // See view::Label's RecalculateColors() for details. const SkColor kRegularTextBackgroundColor = SK_ColorWHITE; const SkColor kDimTextBackgroundColor = SK_ColorWHITE; +const SkColor kContextTextBackgroundColor = SK_ColorWHITE; // static views::Background* MakeBackground( @@ -462,13 +470,17 @@ NotificationView::NotificationView(const Notification& notification, top_view_->set_border(MakeEmptyBorder( kTextTopPadding - 8, 0, kTextBottomPadding - 5, 0)); + const gfx::FontList default_label_font_list = views::Label().font_list(); + // Create the title view if appropriate. title_view_ = NULL; if (!notification.title().empty()) { - gfx::Font font = views::Label().font().DeriveFont(2); - int padding = kTitleLineHeight - font.GetHeight(); + const gfx::FontList& font_list = + default_label_font_list.DeriveFontListWithSizeDelta(2); + int padding = kTitleLineHeight - font_list.GetHeight(); title_view_ = new BoundedLabel( - ui::TruncateString(notification.title(), kTitleCharacterLimit), font); + gfx::TruncateString(notification.title(), kTitleCharacterLimit), + font_list); title_view_->SetLineHeight(kTitleLineHeight); title_view_->SetLineLimit(message_center::kTitleLineLimit); title_view_->SetColors(message_center::kRegularTextColor, @@ -481,18 +493,36 @@ NotificationView::NotificationView(const Notification& notification, // Create the message view if appropriate. message_view_ = NULL; if (!notification.message().empty()) { - int padding = kMessageLineHeight - views::Label().font().GetHeight(); + int padding = kMessageLineHeight - default_label_font_list.GetHeight(); message_view_ = new BoundedLabel( - ui::TruncateString(notification.message(), kMessageCharacterLimit)); + gfx::TruncateString(notification.message(), kMessageCharacterLimit)); message_view_->SetLineHeight(kMessageLineHeight); message_view_->SetVisible(!is_expanded() || !notification.items().size()); - message_view_->SetColors(message_center::kDimTextColor, + message_view_->SetColors(message_center::kRegularTextColor, kDimTextBackgroundColor); message_view_->set_border(MakeTextBorder(padding, 4, 0)); top_view_->AddChildView(message_view_); accessible_lines.push_back(notification.message()); } + // Create the context message view if appropriate. + context_message_view_ = NULL; + if (!notification.context_message().empty()) { + int padding = kMessageLineHeight - default_label_font_list.GetHeight(); + context_message_view_ = + new BoundedLabel(gfx::TruncateString(notification.context_message(), + kContextMessageCharacterLimit), + default_label_font_list); + context_message_view_->SetLineLimit( + message_center::kContextMessageLineLimit); + context_message_view_->SetLineHeight(kMessageLineHeight); + context_message_view_->SetColors(message_center::kDimTextColor, + kContextTextBackgroundColor); + context_message_view_->set_border(MakeTextBorder(padding, 4, 0)); + top_view_->AddChildView(context_message_view_); + accessible_lines.push_back(notification.context_message()); + } + // Create the progress bar view. progress_bar_view_ = NULL; if (notification.type() == NOTIFICATION_TYPE_PROGRESS) { @@ -504,7 +534,7 @@ NotificationView::NotificationView(const Notification& notification, } // Create the list item views (up to a maximum). - int padding = kMessageLineHeight - views::Label().font().GetHeight(); + int padding = kMessageLineHeight - default_label_font_list.GetHeight(); std::vector<NotificationItem> items = notification.items(); for (size_t i = 0; i < items.size() && i < kNotificationMaximumItems; ++i) { ItemView* item_view = new ItemView(items[i]); diff --git a/chromium/ui/message_center/views/notification_view.h b/chromium/ui/message_center/views/notification_view.h index 622e2c3bd69..5479939da8c 100644 --- a/chromium/ui/message_center/views/notification_view.h +++ b/chromium/ui/message_center/views/notification_view.h @@ -71,6 +71,7 @@ class MESSAGE_CENTER_EXPORT NotificationView : public MessageView { views::View* top_view_; BoundedLabel* title_view_; BoundedLabel* message_view_; + BoundedLabel* context_message_view_; std::vector<views::View*> item_views_; views::View* icon_view_; views::View* bottom_view_; diff --git a/chromium/ui/message_center/views/notifier_settings_view.cc b/chromium/ui/message_center/views/notifier_settings_view.cc index b4e18846a2b..40982748637 100644 --- a/chromium/ui/message_center/views/notifier_settings_view.cc +++ b/chromium/ui/message_center/views/notifier_settings_view.cc @@ -13,10 +13,10 @@ #include "grit/ui_strings.h" #include "skia/ext/image_operations.h" #include "third_party/skia/include/core/SkColor.h" -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/models/simple_menu_model.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/canvas.h" #include "ui/gfx/image/image.h" #include "ui/gfx/size.h" @@ -419,7 +419,7 @@ void NotifierSettingsView::UpdateContentsView( contents_title_view->AddChildView(top_label); string16 notifier_group_text; - if (provider_) { + if (provider_ && provider_->GetNotifierGroupCount() > 0) { const NotifierGroup& active_group = provider_->GetActiveNotifierGroup(); notifier_group_text = active_group.login_info.empty() ? active_group.name @@ -478,7 +478,6 @@ gfx::Size NotifierSettingsView::GetMinimumSize() { gfx::Size NotifierSettingsView::GetPreferredSize() { gfx::Size preferred_size; - std::vector<gfx::Size> child_sizes; gfx::Size title_size = title_label_->GetPreferredSize(); gfx::Size content_size = scroller_->contents()->GetPreferredSize(); return gfx::Size(std::max(title_size.width(), content_size.width()), diff --git a/chromium/ui/message_center/views/toast_contents_view.cc b/chromium/ui/message_center/views/toast_contents_view.cc index b7dae986a20..645c654701c 100644 --- a/chromium/ui/message_center/views/toast_contents_view.cc +++ b/chromium/ui/message_center/views/toast_contents_view.cc @@ -11,8 +11,8 @@ #include "base/time/time.h" #include "base/timer/timer.h" #include "ui/base/accessibility/accessible_view_state.h" -#include "ui/base/animation/animation_delegate.h" -#include "ui/base/animation/slide_animation.h" +#include "ui/gfx/animation/animation_delegate.h" +#include "ui/gfx/animation/slide_animation.h" #include "ui/gfx/display.h" #include "ui/gfx/screen.h" #include "ui/message_center/message_center.h" @@ -59,7 +59,7 @@ ToastContentsView::ToastContentsView( // remains. This is hacky but easier to keep the consistency. set_background(views::Background::CreateSolidBackground(0, 0, 0, 0)); - fade_animation_.reset(new ui::SlideAnimation(this)); + fade_animation_.reset(new gfx::SlideAnimation(this)); fade_animation_->SetSlideDuration(kFadeInOutDuration); } @@ -91,8 +91,22 @@ void ToastContentsView::SetContents(MessageView* view) { Layout(); // If it has the contents already, this invocation means an update of the // popup toast, and the new contents should be read through a11y feature. - if (already_has_contents) - NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_FOCUS, false); + // The notification type should be ALERT, otherwise the accessibility message + // won't be read for this view which returns ROLE_WINDOW. + if (already_has_contents) { + const NotificationList::Notifications& notifications = + message_center_->GetNotifications(); + for (NotificationList::Notifications::const_iterator iter = + notifications.begin(); iter != notifications.end(); ++iter) { + if ((*iter)->id() != id_) + continue; + + const RichNotificationData& optional = (*iter)->rich_notification_data(); + if (optional.should_make_spoken_feedback_for_popup_updates) + NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_ALERT, false); + break; + } + } } void ToastContentsView::RevealWithAnimation(gfx::Point origin) { @@ -153,7 +167,7 @@ void ToastContentsView::SetBoundsWithAnimation(gfx::Rect new_bounds) { if (bounds_animation_.get()) bounds_animation_->Stop(); - bounds_animation_.reset(new ui::SlideAnimation(this)); + bounds_animation_.reset(new gfx::SlideAnimation(this)); bounds_animation_->Show(); } @@ -181,7 +195,7 @@ void ToastContentsView::StartFadeOut() { } void ToastContentsView::OnBoundsAnimationEndedOrCancelled( - const ui::Animation* animation) { + const gfx::Animation* animation) { if (is_closing_ && closing_animation_ == animation && GetWidget()) { views::Widget* widget = GetWidget(); #if defined(USE_AURA) @@ -205,8 +219,8 @@ void ToastContentsView::OnBoundsAnimationEndedOrCancelled( collection_->DecrementDeferCounter(); } -// ui::AnimationDelegate -void ToastContentsView::AnimationProgressed(const ui::Animation* animation) { +// gfx::AnimationDelegate +void ToastContentsView::AnimationProgressed(const gfx::Animation* animation) { if (animation == bounds_animation_.get()) { gfx::Rect current(animation->CurrentValueBetween( animated_bounds_start_, animated_bounds_end_)); @@ -218,12 +232,12 @@ void ToastContentsView::AnimationProgressed(const ui::Animation* animation) { } } -void ToastContentsView::AnimationEnded(const ui::Animation* animation) { +void ToastContentsView::AnimationEnded(const gfx::Animation* animation) { OnBoundsAnimationEndedOrCancelled(animation); } void ToastContentsView::AnimationCanceled( - const ui::Animation* animation) { + const gfx::Animation* animation) { OnBoundsAnimationEndedOrCancelled(animation); } diff --git a/chromium/ui/message_center/views/toast_contents_view.h b/chromium/ui/message_center/views/toast_contents_view.h index 4f26c6acb0c..6b79ac1336e 100644 --- a/chromium/ui/message_center/views/toast_contents_view.h +++ b/chromium/ui/message_center/views/toast_contents_view.h @@ -7,14 +7,14 @@ #include "base/compiler_specific.h" #include "base/memory/weak_ptr.h" -#include "ui/base/animation/animation_delegate.h" +#include "ui/gfx/animation/animation_delegate.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/point.h" #include "ui/gfx/rect.h" #include "ui/gfx/size.h" #include "ui/views/widget/widget_delegate.h" -namespace ui { +namespace gfx { class Animation; class SlideAnimation; } @@ -32,7 +32,7 @@ class Notification; class ToastContentsView : public views::WidgetDelegateView, - public ui::AnimationDelegate { + public gfx::AnimationDelegate { public: ToastContentsView(const Notification* notification, base::WeakPtr<MessagePopupCollection> collection, @@ -71,10 +71,10 @@ class ToastContentsView : public views::WidgetDelegateView, virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; private: - // Overridden from ui::AnimationDelegate: - virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; - virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE; - virtual void AnimationCanceled(const ui::Animation* animation) OVERRIDE; + // Overridden from gfx::AnimationDelegate: + virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; + virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE; + virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE; // Overridden from views::WidgetDelegate: virtual views::View* GetContentsView() OVERRIDE; @@ -90,7 +90,7 @@ class ToastContentsView : public views::WidgetDelegateView, void StartFadeIn(); void StartFadeOut(); // Will call Widget::Close() when animation ends. - void OnBoundsAnimationEndedOrCancelled(const ui::Animation* animation); + void OnBoundsAnimationEndedOrCancelled(const gfx::Animation* animation); base::WeakPtr<MessagePopupCollection> collection_; MessageCenter* message_center_; @@ -98,8 +98,8 @@ class ToastContentsView : public views::WidgetDelegateView, // Id if the corresponding Notification. std::string id_; - scoped_ptr<ui::SlideAnimation> bounds_animation_; - scoped_ptr<ui::SlideAnimation> fade_animation_; + scoped_ptr<gfx::SlideAnimation> bounds_animation_; + scoped_ptr<gfx::SlideAnimation> fade_animation_; bool is_animating_bounds_; gfx::Rect animated_bounds_start_; @@ -108,7 +108,7 @@ class ToastContentsView : public views::WidgetDelegateView, bool is_closing_; // Closing animation - when it ends, close the widget. Weak, only used // for referential equality. - ui::Animation* closing_animation_; + gfx::Animation* closing_animation_; gfx::Point origin_; gfx::Size preferred_size_; diff --git a/chromium/ui/metro_viewer/metro_viewer_messages.h b/chromium/ui/metro_viewer/metro_viewer_messages.h index 9108620653d..7d0bd14f368 100644 --- a/chromium/ui/metro_viewer/metro_viewer_messages.h +++ b/chromium/ui/metro_viewer/metro_viewer_messages.h @@ -8,7 +8,7 @@ #include "base/basictypes.h" #include "ipc/ipc_message_macros.h" -#include "ui/base/events/event_constants.h" +#include "ui/events/event_constants.h" #include "ui/gfx/native_widget_types.h" #define IPC_MESSAGE_START MetroViewerMsgStart @@ -92,6 +92,11 @@ IPC_MESSAGE_CONTROL2(MetroViewerHostMsg_SelectFolderDone, // Messages sent from the browser to the viewer: +// Requests the viewer to open a URL in desktop mode. +IPC_MESSAGE_CONTROL2(MetroViewerHostMsg_OpenURLOnDesktop, + base::FilePath, /* shortcut */ + string16 /* url */); + // Requests the viewer to change the pointer to a new cursor. IPC_MESSAGE_CONTROL1(MetroViewerHostMsg_SetCursor, int64 /* cursor */); @@ -132,11 +137,6 @@ IPC_MESSAGE_CONTROL4(MetroViewerHostMsg_DisplayFileOpen, IPC_MESSAGE_CONTROL1(MetroViewerHostMsg_DisplaySelectFolder, string16) /* title */ -// Informs the browser about the viewer activation state, i.e. active, lost -// activation etc. -IPC_MESSAGE_CONTROL1(MetroViewerHostMsg_WindowActivated, - bool) /* active */ - // Sent to the viewer process to set the cursor position. IPC_MESSAGE_CONTROL2(MetroViewerHostMsg_SetCursorPos, int, /* x */ diff --git a/chromium/ui/native_theme/common_theme.cc b/chromium/ui/native_theme/common_theme.cc index b589c000b82..8c5a964e312 100644 --- a/chromium/ui/native_theme/common_theme.cc +++ b/chromium/ui/native_theme/common_theme.cc @@ -21,8 +21,7 @@ namespace { // MenuItem: const SkColor kMenuBackgroundColor = SK_ColorWHITE; -const SkColor kMenuHighlightBackgroundColor = SkColorSetARGB(15, 0, 0, 0); -const SkColor kMenuHighlightBackgroundColor2 = SkColorSetRGB(0x42, 0x81, 0xF4); +const SkColor kMenuHighlightBackgroundColor = SkColorSetRGB(0x42, 0x81, 0xF4); const SkColor kMenuInvertedSchemeHighlightBackgroundColor = SkColorSetRGB(48, 48, 48); const SkColor kMenuBorderColor = SkColorSetRGB(0xBA, 0xBA, 0xBA); @@ -73,7 +72,7 @@ bool CommonThemeGetSystemColor(NativeTheme::ColorId color_id, SkColor* color) { *color = kDisabledMenuItemForegroundColor; break; case NativeTheme::kColorId_SelectedMenuItemForegroundColor: - *color = kEnabledMenuItemForegroundColor; + *color = SK_ColorWHITE; break; case NativeTheme::kColorId_ButtonDisabledColor: *color = kDisabledMenuItemForegroundColor; @@ -82,8 +81,6 @@ bool CommonThemeGetSystemColor(NativeTheme::ColorId color_id, SkColor* color) { return false; } - *color = AdjustColorForMenuVariations(color_id, *color); - if (gfx::IsInvertedColorScheme()) { switch (color_id) { case NativeTheme::kColorId_FocusedMenuItemBackgroundColor: @@ -168,19 +165,4 @@ void CommonThemePaintMenuItemBackground(SkCanvas* canvas, canvas->drawRect(gfx::RectToSkRect(rect), paint); } -SkColor AdjustColorForMenuVariations(NativeTheme::ColorId color_id, - SkColor color) { - if (NativeTheme::GetMenuVariation() != NativeTheme::MENU_VARIATION_CONTRAST) - return color; - - switch(color_id) { - case NativeTheme::kColorId_FocusedMenuItemBackgroundColor: - return kMenuHighlightBackgroundColor2; - case NativeTheme::kColorId_SelectedMenuItemForegroundColor: - return SK_ColorWHITE; - default: - return color; - } -} - } // namespace ui diff --git a/chromium/ui/native_theme/common_theme.h b/chromium/ui/native_theme/common_theme.h index 530032f8390..c91f4899c82 100644 --- a/chromium/ui/native_theme/common_theme.h +++ b/chromium/ui/native_theme/common_theme.h @@ -39,13 +39,6 @@ void NATIVE_THEME_EXPORT CommonThemePaintMenuItemBackground( NativeTheme::State state, const gfx::Rect& rect); -// Adjust some colors for menu Finch experiments. -// |color_id| id of a color to be adjusted. -// |color| color before adjustment. -// Returns adjusted color. -SkColor AdjustColorForMenuVariations(NativeTheme::ColorId color_id, - SkColor color); - } // namespace ui #endif // UI_NATIVE_THEME_COMMON_THEME_H_ diff --git a/chromium/ui/native_theme/native_theme.cc b/chromium/ui/native_theme/native_theme.cc index af44a7f9eb2..8cb845cc306 100644 --- a/chromium/ui/native_theme/native_theme.cc +++ b/chromium/ui/native_theme/native_theme.cc @@ -4,16 +4,6 @@ #include "ui/native_theme/native_theme.h" -#include "base/command_line.h" -#include "base/metrics/field_trial.h" - - -// Constants for the new menu style field trial. -const char kMenuVariationFieldTrialName[] = "NewMenuStyle"; -const char kMenuVariationFieldTrialGroupNameCompact1[] = "Compact1"; -const char kMenuVariationFieldTrialGroupNameCompact2[] = "Compact2"; -const char kMenuVariationFieldTrialGroupNameHigherContrast[] = "HigherContrast"; - namespace ui { void NativeTheme::SetScrollbarColors(unsigned inactive_color, @@ -27,20 +17,6 @@ void NativeTheme::SetScrollbarColors(unsigned inactive_color, // NativeTheme::instance() is implemented in the platform specific source files, // such as native_theme_win.cc or native_theme_linux.cc -// static -NativeTheme::MenuVariation NativeTheme::GetMenuVariation() { - std::string trial_group_name = - base::FieldTrialList::FindFullName(kMenuVariationFieldTrialName); - if (trial_group_name == kMenuVariationFieldTrialGroupNameCompact1) - return MENU_VARIATION_COMPACT_1; - if (trial_group_name == kMenuVariationFieldTrialGroupNameCompact2) - return MENU_VARIATION_COMPACT_2; - if (trial_group_name == kMenuVariationFieldTrialGroupNameHigherContrast) - return MENU_VARIATION_CONTRAST; - - return MENU_VARIATION_NORMAL; -} - NativeTheme::NativeTheme() : thumb_inactive_color_(0xeaeaea), thumb_active_color_(0xf4f4f4), diff --git a/chromium/ui/native_theme/native_theme.h b/chromium/ui/native_theme/native_theme.h index 30379169e37..98974145570 100644 --- a/chromium/ui/native_theme/native_theme.h +++ b/chromium/ui/native_theme/native_theme.h @@ -85,13 +85,6 @@ class NATIVE_THEME_EXPORT NativeTheme { kMaxState, }; - enum MenuVariation { - MENU_VARIATION_NORMAL, - MENU_VARIATION_COMPACT_1, - MENU_VARIATION_COMPACT_2, - MENU_VARIATION_CONTRAST - }; - // Each structure below holds extra information needed when painting a given // part. @@ -296,8 +289,6 @@ class NATIVE_THEME_EXPORT NativeTheme { // function, returning the port's subclass. static NativeTheme* instance(); - static MenuVariation GetMenuVariation(); - protected: NativeTheme(); virtual ~NativeTheme(); diff --git a/chromium/ui/native_theme/native_theme_win.cc b/chromium/ui/native_theme/native_theme_win.cc index 1839de32263..74b4f14a261 100644 --- a/chromium/ui/native_theme/native_theme_win.cc +++ b/chromium/ui/native_theme/native_theme_win.cc @@ -23,12 +23,12 @@ #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkColorPriv.h" #include "third_party/skia/include/core/SkShader.h" -#include "ui/base/win/dpi.h" #include "ui/gfx/color_utils.h" #include "ui/gfx/gdi_util.h" #include "ui/gfx/rect.h" #include "ui/gfx/rect_conversions.h" #include "ui/gfx/sys_color_change_listener.h" +#include "ui/gfx/win/dpi.h" #include "ui/native_theme/common_theme.h" // This was removed from Winvers.h but is still used. @@ -243,7 +243,7 @@ gfx::Size NativeThemeWin::GetPartSize(Part part, case kScrollbarVerticalThumb: case kScrollbarHorizontalTrack: case kScrollbarVerticalTrack: - size.cx = size.cy = ui::win::GetSystemMetricsInDIP(SM_CXVSCROLL); + size.cx = size.cy = gfx::win::GetSystemMetricsInDIP(SM_CXVSCROLL); return gfx::Size(size.cx, size.cy); } diff --git a/chromium/ui/resources/default_100_percent/common/drag_tip_copy.png b/chromium/ui/resources/default_100_percent/common/drag_tip_copy.png Binary files differnew file mode 100644 index 00000000000..349c7c6d9d3 --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/drag_tip_copy.png diff --git a/chromium/ui/resources/default_100_percent/common/drag_tip_link.png b/chromium/ui/resources/default_100_percent/common/drag_tip_link.png Binary files differnew file mode 100644 index 00000000000..8f61a39dd20 --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/drag_tip_link.png diff --git a/chromium/ui/resources/default_100_percent/common/drag_tip_move.png b/chromium/ui/resources/default_100_percent/common/drag_tip_move.png Binary files differnew file mode 100644 index 00000000000..a897ef4799a --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/drag_tip_move.png diff --git a/chromium/ui/resources/default_100_percent/common/drag_tip_nodrop.png b/chromium/ui/resources/default_100_percent/common/drag_tip_nodrop.png Binary files differnew file mode 100644 index 00000000000..917cb5f1922 --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/drag_tip_nodrop.png diff --git a/chromium/ui/resources/default_100_percent/common/notification_clear_all_disabled.png b/chromium/ui/resources/default_100_percent/common/notification_clear_all_disabled.png Binary files differindex a15a261e027..1aa1857e0e9 100644 --- a/chromium/ui/resources/default_100_percent/common/notification_clear_all_disabled.png +++ b/chromium/ui/resources/default_100_percent/common/notification_clear_all_disabled.png diff --git a/chromium/ui/resources/default_100_percent/common/pointers/alias_big.png b/chromium/ui/resources/default_100_percent/common/pointers/alias_big.png Binary files differnew file mode 100644 index 00000000000..283bf7f48fe --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/pointers/alias_big.png diff --git a/chromium/ui/resources/default_100_percent/common/pointers/cell_big.png b/chromium/ui/resources/default_100_percent/common/pointers/cell_big.png Binary files differnew file mode 100644 index 00000000000..3dec5e5d825 --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/pointers/cell_big.png diff --git a/chromium/ui/resources/default_100_percent/common/pointers/context_menu_big.png b/chromium/ui/resources/default_100_percent/common/pointers/context_menu_big.png Binary files differnew file mode 100644 index 00000000000..7c9e250d488 --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/pointers/context_menu_big.png diff --git a/chromium/ui/resources/default_100_percent/common/pointers/copy_big.png b/chromium/ui/resources/default_100_percent/common/pointers/copy_big.png Binary files differnew file mode 100644 index 00000000000..18f4696ffc2 --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/pointers/copy_big.png diff --git a/chromium/ui/resources/default_100_percent/common/pointers/crosshair_big.png b/chromium/ui/resources/default_100_percent/common/pointers/crosshair_big.png Binary files differnew file mode 100644 index 00000000000..ea1f5fc07ff --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/pointers/crosshair_big.png diff --git a/chromium/ui/resources/default_100_percent/common/pointers/fleur_big.png b/chromium/ui/resources/default_100_percent/common/pointers/fleur_big.png Binary files differnew file mode 100644 index 00000000000..2e327661d68 --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/pointers/fleur_big.png diff --git a/chromium/ui/resources/default_100_percent/common/pointers/hand2_big.png b/chromium/ui/resources/default_100_percent/common/pointers/hand2_big.png Binary files differnew file mode 100644 index 00000000000..785047f7cdf --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/pointers/hand2_big.png diff --git a/chromium/ui/resources/default_100_percent/common/pointers/hand3_big.png b/chromium/ui/resources/default_100_percent/common/pointers/hand3_big.png Binary files differnew file mode 100644 index 00000000000..3c547517392 --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/pointers/hand3_big.png diff --git a/chromium/ui/resources/default_100_percent/common/pointers/help_big.png b/chromium/ui/resources/default_100_percent/common/pointers/help_big.png Binary files differnew file mode 100644 index 00000000000..6552f9bb333 --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/pointers/help_big.png diff --git a/chromium/ui/resources/default_100_percent/common/pointers/left_ptr_big.png b/chromium/ui/resources/default_100_percent/common/pointers/left_ptr_big.png Binary files differnew file mode 100644 index 00000000000..c5604c74915 --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/pointers/left_ptr_big.png diff --git a/chromium/ui/resources/default_100_percent/common/pointers/move_big.png b/chromium/ui/resources/default_100_percent/common/pointers/move_big.png Binary files differnew file mode 100644 index 00000000000..c29db870273 --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/pointers/move_big.png diff --git a/chromium/ui/resources/default_100_percent/common/pointers/nodrop_big.png b/chromium/ui/resources/default_100_percent/common/pointers/nodrop_big.png Binary files differnew file mode 100644 index 00000000000..da981df3de2 --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/pointers/nodrop_big.png diff --git a/chromium/ui/resources/default_100_percent/common/pointers/sb_h_double_arrow_big.png b/chromium/ui/resources/default_100_percent/common/pointers/sb_h_double_arrow_big.png Binary files differnew file mode 100644 index 00000000000..49dc3d303bf --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/pointers/sb_h_double_arrow_big.png diff --git a/chromium/ui/resources/default_100_percent/common/pointers/sb_v_double_arrow_big.png b/chromium/ui/resources/default_100_percent/common/pointers/sb_v_double_arrow_big.png Binary files differnew file mode 100644 index 00000000000..fd777b14bad --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/pointers/sb_v_double_arrow_big.png diff --git a/chromium/ui/resources/default_100_percent/common/pointers/top_left_corner_big.png b/chromium/ui/resources/default_100_percent/common/pointers/top_left_corner_big.png Binary files differnew file mode 100644 index 00000000000..eecaa89204e --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/pointers/top_left_corner_big.png diff --git a/chromium/ui/resources/default_100_percent/common/pointers/top_right_corner_big.png b/chromium/ui/resources/default_100_percent/common/pointers/top_right_corner_big.png Binary files differnew file mode 100644 index 00000000000..9d47ecf793e --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/pointers/top_right_corner_big.png diff --git a/chromium/ui/resources/default_100_percent/common/pointers/xterm_big.png b/chromium/ui/resources/default_100_percent/common/pointers/xterm_big.png Binary files differnew file mode 100644 index 00000000000..2fba190552b --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/pointers/xterm_big.png diff --git a/chromium/ui/resources/default_100_percent/common/pointers/xterm_horiz_big.png b/chromium/ui/resources/default_100_percent/common/pointers/xterm_horiz_big.png Binary files differnew file mode 100644 index 00000000000..94f5ddc59ac --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/pointers/xterm_horiz_big.png diff --git a/chromium/ui/resources/default_100_percent/common/pointers/zoom_in_big.png b/chromium/ui/resources/default_100_percent/common/pointers/zoom_in_big.png Binary files differnew file mode 100644 index 00000000000..923ad792264 --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/pointers/zoom_in_big.png diff --git a/chromium/ui/resources/default_100_percent/common/pointers/zoom_out_big.png b/chromium/ui/resources/default_100_percent/common/pointers/zoom_out_big.png Binary files differnew file mode 100644 index 00000000000..aa47eb94fbc --- /dev/null +++ b/chromium/ui/resources/default_100_percent/common/pointers/zoom_out_big.png diff --git a/chromium/ui/resources/default_100_percent/mac/notification_tray_attention.png b/chromium/ui/resources/default_100_percent/mac/notification_tray_attention.png Binary files differindex 6e4910943cb..f6fe8298b61 100644 --- a/chromium/ui/resources/default_100_percent/mac/notification_tray_attention.png +++ b/chromium/ui/resources/default_100_percent/mac/notification_tray_attention.png diff --git a/chromium/ui/resources/default_100_percent/mac/notification_tray_attention_pressed.png b/chromium/ui/resources/default_100_percent/mac/notification_tray_attention_pressed.png Binary files differindex 931a4abcaf2..e4f8cdb5dd9 100644 --- a/chromium/ui/resources/default_100_percent/mac/notification_tray_attention_pressed.png +++ b/chromium/ui/resources/default_100_percent/mac/notification_tray_attention_pressed.png diff --git a/chromium/ui/resources/default_100_percent/mac/notification_tray_do_not_disturb_attention.png b/chromium/ui/resources/default_100_percent/mac/notification_tray_do_not_disturb_attention.png Binary files differindex 335a302712c..042673f535c 100644 --- a/chromium/ui/resources/default_100_percent/mac/notification_tray_do_not_disturb_attention.png +++ b/chromium/ui/resources/default_100_percent/mac/notification_tray_do_not_disturb_attention.png diff --git a/chromium/ui/resources/default_100_percent/mac/notification_tray_do_not_disturb_attention_pressed.png b/chromium/ui/resources/default_100_percent/mac/notification_tray_do_not_disturb_attention_pressed.png Binary files differindex 7ab9ee0b751..95a681ad4e8 100644 --- a/chromium/ui/resources/default_100_percent/mac/notification_tray_do_not_disturb_attention_pressed.png +++ b/chromium/ui/resources/default_100_percent/mac/notification_tray_do_not_disturb_attention_pressed.png diff --git a/chromium/ui/resources/default_100_percent/mac/notification_tray_do_not_disturb_empty.png b/chromium/ui/resources/default_100_percent/mac/notification_tray_do_not_disturb_empty.png Binary files differindex 3c9149e6f12..84330824e72 100644 --- a/chromium/ui/resources/default_100_percent/mac/notification_tray_do_not_disturb_empty.png +++ b/chromium/ui/resources/default_100_percent/mac/notification_tray_do_not_disturb_empty.png diff --git a/chromium/ui/resources/default_100_percent/mac/notification_tray_do_not_disturb_empty_pressed.png b/chromium/ui/resources/default_100_percent/mac/notification_tray_do_not_disturb_empty_pressed.png Binary files differindex 87acf99e3d5..e0f7f234e52 100644 --- a/chromium/ui/resources/default_100_percent/mac/notification_tray_do_not_disturb_empty_pressed.png +++ b/chromium/ui/resources/default_100_percent/mac/notification_tray_do_not_disturb_empty_pressed.png diff --git a/chromium/ui/resources/default_100_percent/mac/notification_tray_empty.png b/chromium/ui/resources/default_100_percent/mac/notification_tray_empty.png Binary files differindex db17be92556..53ad499d459 100644 --- a/chromium/ui/resources/default_100_percent/mac/notification_tray_empty.png +++ b/chromium/ui/resources/default_100_percent/mac/notification_tray_empty.png diff --git a/chromium/ui/resources/default_100_percent/mac/notification_tray_empty_pressed.png b/chromium/ui/resources/default_100_percent/mac/notification_tray_empty_pressed.png Binary files differindex 2f3d8fca7c1..15d30bf68f6 100644 --- a/chromium/ui/resources/default_100_percent/mac/notification_tray_empty_pressed.png +++ b/chromium/ui/resources/default_100_percent/mac/notification_tray_empty_pressed.png diff --git a/chromium/ui/resources/default_100_percent/win/app_list_user_indicator.png b/chromium/ui/resources/default_100_percent/win/app_list_user_indicator.png Binary files differnew file mode 100644 index 00000000000..77f58588790 --- /dev/null +++ b/chromium/ui/resources/default_100_percent/win/app_list_user_indicator.png diff --git a/chromium/ui/resources/default_200_percent/common/drag_tip_copy.png b/chromium/ui/resources/default_200_percent/common/drag_tip_copy.png Binary files differnew file mode 100644 index 00000000000..0c2d609f2ca --- /dev/null +++ b/chromium/ui/resources/default_200_percent/common/drag_tip_copy.png diff --git a/chromium/ui/resources/default_200_percent/common/drag_tip_link.png b/chromium/ui/resources/default_200_percent/common/drag_tip_link.png Binary files differnew file mode 100644 index 00000000000..fe0fd25d144 --- /dev/null +++ b/chromium/ui/resources/default_200_percent/common/drag_tip_link.png diff --git a/chromium/ui/resources/default_200_percent/common/drag_tip_move.png b/chromium/ui/resources/default_200_percent/common/drag_tip_move.png Binary files differnew file mode 100644 index 00000000000..e2374ece106 --- /dev/null +++ b/chromium/ui/resources/default_200_percent/common/drag_tip_move.png diff --git a/chromium/ui/resources/default_200_percent/common/drag_tip_nodrop.png b/chromium/ui/resources/default_200_percent/common/drag_tip_nodrop.png Binary files differnew file mode 100644 index 00000000000..e735e422ef8 --- /dev/null +++ b/chromium/ui/resources/default_200_percent/common/drag_tip_nodrop.png diff --git a/chromium/ui/resources/default_200_percent/mac/notification_tray_attention.png b/chromium/ui/resources/default_200_percent/mac/notification_tray_attention.png Binary files differindex 6587f34bb8e..c0b374bd17a 100644 --- a/chromium/ui/resources/default_200_percent/mac/notification_tray_attention.png +++ b/chromium/ui/resources/default_200_percent/mac/notification_tray_attention.png diff --git a/chromium/ui/resources/default_200_percent/mac/notification_tray_attention_pressed.png b/chromium/ui/resources/default_200_percent/mac/notification_tray_attention_pressed.png Binary files differindex 7d2521c790b..5e12a8fe568 100644 --- a/chromium/ui/resources/default_200_percent/mac/notification_tray_attention_pressed.png +++ b/chromium/ui/resources/default_200_percent/mac/notification_tray_attention_pressed.png diff --git a/chromium/ui/resources/default_200_percent/mac/notification_tray_do_not_disturb_attention.png b/chromium/ui/resources/default_200_percent/mac/notification_tray_do_not_disturb_attention.png Binary files differindex f0584e43351..804beb6f289 100644 --- a/chromium/ui/resources/default_200_percent/mac/notification_tray_do_not_disturb_attention.png +++ b/chromium/ui/resources/default_200_percent/mac/notification_tray_do_not_disturb_attention.png diff --git a/chromium/ui/resources/default_200_percent/mac/notification_tray_do_not_disturb_attention_pressed.png b/chromium/ui/resources/default_200_percent/mac/notification_tray_do_not_disturb_attention_pressed.png Binary files differindex 8f922347de3..e8e1e2454e9 100644 --- a/chromium/ui/resources/default_200_percent/mac/notification_tray_do_not_disturb_attention_pressed.png +++ b/chromium/ui/resources/default_200_percent/mac/notification_tray_do_not_disturb_attention_pressed.png diff --git a/chromium/ui/resources/default_200_percent/mac/notification_tray_do_not_disturb_empty.png b/chromium/ui/resources/default_200_percent/mac/notification_tray_do_not_disturb_empty.png Binary files differindex 2370e7acdec..0d2e894db45 100644 --- a/chromium/ui/resources/default_200_percent/mac/notification_tray_do_not_disturb_empty.png +++ b/chromium/ui/resources/default_200_percent/mac/notification_tray_do_not_disturb_empty.png diff --git a/chromium/ui/resources/default_200_percent/mac/notification_tray_do_not_disturb_empty_pressed.png b/chromium/ui/resources/default_200_percent/mac/notification_tray_do_not_disturb_empty_pressed.png Binary files differindex 1c6a7af60e7..7376b2f2127 100644 --- a/chromium/ui/resources/default_200_percent/mac/notification_tray_do_not_disturb_empty_pressed.png +++ b/chromium/ui/resources/default_200_percent/mac/notification_tray_do_not_disturb_empty_pressed.png diff --git a/chromium/ui/resources/default_200_percent/mac/notification_tray_empty.png b/chromium/ui/resources/default_200_percent/mac/notification_tray_empty.png Binary files differindex e3fc1f3bfbe..f840d93a70e 100644 --- a/chromium/ui/resources/default_200_percent/mac/notification_tray_empty.png +++ b/chromium/ui/resources/default_200_percent/mac/notification_tray_empty.png diff --git a/chromium/ui/resources/default_200_percent/mac/notification_tray_empty_pressed.png b/chromium/ui/resources/default_200_percent/mac/notification_tray_empty_pressed.png Binary files differindex 21492e85dcf..f6f24b70f29 100644 --- a/chromium/ui/resources/default_200_percent/mac/notification_tray_empty_pressed.png +++ b/chromium/ui/resources/default_200_percent/mac/notification_tray_empty_pressed.png diff --git a/chromium/ui/resources/default_200_percent/win/app_list_user_indicator.png b/chromium/ui/resources/default_200_percent/win/app_list_user_indicator.png Binary files differnew file mode 100644 index 00000000000..9fb3a484c00 --- /dev/null +++ b/chromium/ui/resources/default_200_percent/win/app_list_user_indicator.png diff --git a/chromium/ui/resources/resource_check/resource_scale_factors.py b/chromium/ui/resources/resource_check/resource_scale_factors.py index f974447ccf2..9ddc70fda60 100644 --- a/chromium/ui/resources/resource_check/resource_scale_factors.py +++ b/chromium/ui/resources/resource_check/resource_scale_factors.py @@ -15,6 +15,10 @@ import os import struct +class InvalidPNGException(Exception): + pass + + class ResourceScaleFactors(object): """Verifier of image dimensions for Chromium resources. @@ -44,7 +48,8 @@ class ResourceScaleFactors(object): def ImageSize(filename): with open(filename, 'rb', buffering=0) as f: data = f.read(24) - assert data[:8] == '\x89PNG\r\n\x1A\n' and data[12:16] == 'IHDR' + if data[:8] != '\x89PNG\r\n\x1A\n' or data[12:16] != 'IHDR': + raise InvalidPNGException return struct.unpack('>ii', data[16:24]) # Returns a list of valid scaled image sizes. The valid sizes are the @@ -75,6 +80,9 @@ class ResourceScaleFactors(object): if relative_path not in files: files.append(relative_path) + corrupt_png_error = ('Corrupt PNG in file %s. Note that binaries are not ' + 'correctly uploaded to the code review tool and must be directly ' + 'submitted using the dcommit command.') for f in files: base_image = self.input_api.os_path.join(self.paths[0][1], f) if not os.path.exists(base_image): @@ -82,7 +90,12 @@ class ResourceScaleFactors(object): 'Base image %s does not exist' % self.input_api.os_path.join( repository_path, base_image))) continue - base_dimensions = ImageSize(base_image) + try: + base_dimensions = ImageSize(base_image) + except InvalidPNGException: + results.append(self.output_api.PresubmitError(corrupt_png_error % + self.input_api.os_path.join(repository_path, base_image))) + continue # Find all scaled versions of the base image and verify their sizes. for i in range(1, len(self.paths)): image_path = self.input_api.os_path.join(self.paths[i][1], f) @@ -90,7 +103,12 @@ class ResourceScaleFactors(object): continue # Ensure that each image for a particular scale factor is the # correct scale of the base image. - scaled_dimensions = ImageSize(image_path) + try: + scaled_dimensions = ImageSize(image_path) + except InvalidPNGException: + results.append(self.output_api.PresubmitError(corrupt_png_error % + self.input_api.os_path.join(repository_path, image_path))) + continue for dimension_name, base_size, scaled_size in zip( ('width', 'height'), base_dimensions, scaled_dimensions): valid_sizes = ValidSizes(base_size, self.paths[i][0]) diff --git a/chromium/ui/resources/ui_resources.grd b/chromium/ui/resources/ui_resources.grd index 067e2eaa925..06043de76f3 100644 --- a/chromium/ui/resources/ui_resources.grd +++ b/chromium/ui/resources/ui_resources.grd @@ -25,10 +25,12 @@ <structure type="chrome_scaled_image" name="IDR_APP_LIST_ITEM_PROGRESS_LEFT" file="common/app_list_progress_bar_left.png" /> <structure type="chrome_scaled_image" name="IDR_APP_LIST_ITEM_PROGRESS_CENTER" file="common/app_list_progress_bar_center.png" /> <structure type="chrome_scaled_image" name="IDR_APP_LIST_ITEM_PROGRESS_RIGHT" file="common/app_list_progress_bar_right.png" /> - <structure type="chrome_scaled_image" name="IDR_APP_LIST_USER_INDICATOR" file="common/app_list_user_indicator.png" /> <structure type="chrome_scaled_image" name="IDR_APP_LIST_TOOLS_HOVER" file="common/app_list_tools_hover.png" /> <structure type="chrome_scaled_image" name="IDR_APP_LIST_TOOLS_NORMAL" file="common/app_list_tools_normal.png" /> <structure type="chrome_scaled_image" name="IDR_APP_LIST_TOOLS_PRESSED" file="common/app_list_tools_pressed.png" /> + <if expr="is_win"> + <structure type="chrome_scaled_image" name="IDR_APP_LIST_USER_INDICATOR" file="win/app_list_user_indicator.png" /> + </if> </if> <structure type="chrome_scaled_image" name="IDR_APP_TOP_CENTER" file="app_top_center.png" /> <if expr="pp_ifdef('toolkit_views')"> @@ -36,6 +38,37 @@ <structure type="chrome_scaled_image" name="IDR_APP_TOP_RIGHT" file="app_top_right.png" /> </if> <if expr="is_linux and pp_ifdef('use_aura')"> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_ALIAS" file="common/pointers/alias_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_CELL" file="common/pointers/cell_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_COL_RESIZE" file="common/pointers/sb_h_double_arrow_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_CONTEXT_MENU" file="common/pointers/context_menu_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_COPY" file="common/pointers/copy_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_CROSSHAIR" file="common/pointers/crosshair_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_EAST_RESIZE" file="common/pointers/sb_h_double_arrow_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_EAST_WEST_RESIZE" file="common/pointers/sb_h_double_arrow_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_FLEUR" file="common/pointers/fleur_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_HAND" file="common/pointers/hand2_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_HELP" file="common/pointers/help_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_IBEAM" file="common/pointers/xterm_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_MOVE" file="common/pointers/move_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_NORTH_EAST_RESIZE" file="common/pointers/top_right_corner_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_NORTH_EAST_SOUTH_WEST_RESIZE" file="common/pointers/top_right_corner_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_NORTH_RESIZE" file="common/pointers/sb_v_double_arrow_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_NORTH_SOUTH_RESIZE" file="common/pointers/sb_v_double_arrow_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_NORTH_WEST_RESIZE" file="common/pointers/top_left_corner_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_NORTH_WEST_SOUTH_EAST_RESIZE" file="common/pointers/top_left_corner_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_NO_DROP" file="common/pointers/nodrop_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_PTR" file="common/pointers/left_ptr_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_ROW_RESIZE" file="common/pointers/sb_v_double_arrow_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_SOUTH_EAST_RESIZE" file="common/pointers/top_left_corner_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_SOUTH_RESIZE" file="common/pointers/sb_v_double_arrow_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_SOUTH_WEST_RESIZE" file="common/pointers/top_right_corner_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_WEST_RESIZE" file="common/pointers/sb_h_double_arrow_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_XTERM_HORIZ" file="common/pointers/xterm_horiz_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_ZOOM_IN" file="common/pointers/zoom_in_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_ZOOM_OUT" file="common/pointers/zoom_out_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_GRAB" file="common/pointers/fleur_big.png" /> + <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_GRABBING" file="common/pointers/hand3_big.png" /> <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_ALIAS" file="common/pointers/alias.png" /> <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_CELL" file="common/pointers/cell.png" /> <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_COL_RESIZE" file="common/pointers/sb_h_double_arrow.png" /> @@ -154,10 +187,10 @@ <structure type="chrome_scaled_image" name="IDR_RADIO_HOVER" file="common/radio_hover.png" /> <structure type="chrome_scaled_image" name="IDR_RADIO_PRESSED" file="common/radio_pressed.png" /> <structure type="chrome_scaled_image" name="IDR_TEXT_SELECTION_HANDLE" file="common/text_selection_handle_small.png" /> - <if expr="not pp_ifdef('toolkit_views') and is_posix and not is_macosx"> + <if expr="pp_ifdef('desktop_linux')"> <structure type="chrome_scaled_image" name="IDR_CLOSE" file="linux/linux_close.png" /> </if> - <if expr="pp_ifdef('toolkit_views')"> + <if expr="not pp_ifdef('desktop_linux') and pp_ifdef('toolkit_views')"> <structure type="chrome_scaled_image" name="IDR_CLOSE" file="close.png" /> </if> <structure type="chrome_scaled_image" name="IDR_CLOSE_2" file="close_2.png" /> @@ -167,13 +200,15 @@ <structure type="chrome_scaled_image" name="IDR_CLOSE_DIALOG" file="close_dialog.png" /> <structure type="chrome_scaled_image" name="IDR_CLOSE_DIALOG_H" file="close_dialog_hover.png" /> <structure type="chrome_scaled_image" name="IDR_CLOSE_DIALOG_P" file="close_dialog_pressed.png" /> - <if expr="not pp_ifdef('toolkit_views') and is_posix and not is_macosx"> + <if expr="pp_ifdef('desktop_linux')"> <structure type="chrome_scaled_image" name="IDR_CLOSE_H" file="linux/linux_close_hover.png" /> <structure type="chrome_scaled_image" name="IDR_CLOSE_P" file="linux/linux_close_pressed.png" /> </if> - <if expr="pp_ifdef('toolkit_views')"> + <if expr="not pp_ifdef('desktop_linux') and pp_ifdef('toolkit_views')"> <structure type="chrome_scaled_image" name="IDR_CLOSE_H" file="close_hover.png" /> <structure type="chrome_scaled_image" name="IDR_CLOSE_P" file="close_pressed.png" /> + </if> + <if expr="pp_ifdef('toolkit_views')"> <structure type="chrome_scaled_image" name="IDR_CLOSE_SA" file="close_sa.png" /> <structure type="chrome_scaled_image" name="IDR_CLOSE_SA_H" file="close_sa_hover.png" /> <structure type="chrome_scaled_image" name="IDR_CLOSE_SA_P" file="close_sa_pressed.png" /> @@ -193,18 +228,20 @@ <structure type="chrome_scaled_image" name="IDR_FRAME" file="frame_default.png" /> <structure type="chrome_scaled_image" name="IDR_FRAME_APP_PANEL" file="frame_app_panel_default.png" /> <structure type="chrome_scaled_image" name="IDR_FRAME_INACTIVE" file="frame_default_inactive.png" /> - <if expr="not pp_ifdef('toolkit_views') and is_posix and not is_macosx"> + <if expr="pp_ifdef('desktop_linux')"> <structure type="chrome_scaled_image" name="IDR_MAXIMIZE" file="linux/linux_maximize.png" /> <structure type="chrome_scaled_image" name="IDR_MAXIMIZE_H" file="linux/linux_maximize_hover.png" /> <structure type="chrome_scaled_image" name="IDR_MAXIMIZE_P" file="linux/linux_maximize_pressed.png" /> </if> - <if expr="pp_ifdef('toolkit_views')"> + <if expr="not pp_ifdef('desktop_linux') and pp_ifdef('toolkit_views')"> <structure type="chrome_scaled_image" name="IDR_MAXIMIZE" file="maximize.png" /> <structure type="chrome_scaled_image" name="IDR_MAXIMIZE_H" file="maximize_hover.png" /> <structure type="chrome_scaled_image" name="IDR_MAXIMIZE_P" file="maximize_pressed.png" /> + </if> + <if expr="pp_ifdef('toolkit_views')"> <structure type="chrome_scaled_image" name="IDR_MENU_HIERARCHY_ARROW" file="common/menu_hierarchy_arrow.png" /> </if> - <if expr="is_macosx"> + <if expr="is_macosx or is_ios"> <structure type="chrome_scaled_image" name="IDR_MENU_HIERARCHY_ARROW" file="mac/menu_hierarchy_arrow.png" /> </if> <if expr="pp_ifdef('toolkit_views')"> @@ -226,12 +263,12 @@ </if> <structure type="chrome_scaled_image" name="IDR_MENU_DROPARROW" file="cros/menu_droparrow.png" /> <structure type="chrome_scaled_image" name="IDR_MESSAGE_CLOSE" file="common/message_close.png" /> - <if expr="not pp_ifdef('toolkit_views') and is_posix and not is_macosx"> + <if expr="pp_ifdef('desktop_linux')"> <structure type="chrome_scaled_image" name="IDR_MINIMIZE" file="linux/linux_minimize.png" /> <structure type="chrome_scaled_image" name="IDR_MINIMIZE_H" file="linux/linux_minimize_hover.png" /> <structure type="chrome_scaled_image" name="IDR_MINIMIZE_P" file="linux/linux_minimize_pressed.png" /> </if> - <if expr="pp_ifdef('toolkit_views')"> + <if expr="not pp_ifdef('desktop_linux') and pp_ifdef('toolkit_views')"> <structure type="chrome_scaled_image" name="IDR_MINIMIZE" file="minimize.png" /> <structure type="chrome_scaled_image" name="IDR_MINIMIZE_H" file="minimize_hover.png" /> <structure type="chrome_scaled_image" name="IDR_MINIMIZE_P" file="minimize_pressed.png" /> @@ -272,7 +309,7 @@ <structure type="chrome_scaled_image" name="IDR_PANEL_TOP_RIGHT_CORNER" file="panel_top_right_corner.png" /> <structure type="chrome_scaled_image" name="IDR_PANEL_BOTTOM_LEFT_CORNER" file="panel_bottom_left_corner.png" /> <structure type="chrome_scaled_image" name="IDR_PANEL_BOTTOM_RIGHT_CORNER" file="panel_bottom_right_corner.png" /> - <if expr="is_posix and not is_macosx and not pp_ifdef('use_aura')"> + <if expr="is_posix and not is_macosx and not is_ios and not pp_ifdef('use_aura')"> <structure type="chrome_scaled_image" name="IDR_PROGRESS_BAR" file="linux/linux-progress-bar.png" /> <structure type="chrome_scaled_image" name="IDR_PROGRESS_BORDER_LEFT" file="linux/linux-progress-border-left.png" /> <structure type="chrome_scaled_image" name="IDR_PROGRESS_BORDER_RIGHT" file="linux/linux-progress-border-right.png" /> @@ -309,12 +346,12 @@ <structure type="chrome_scaled_image" name="IDR_SCROLL_THUMB_VERTICAL_TOP_H" file="cros/aura_scrollbar_thumb_vertical_hover_top.png" /> <structure type="chrome_scaled_image" name="IDR_SCROLL_THUMB_VERTICAL_TOP_P" file="cros/aura_scrollbar_thumb_vertical_pressed_top.png" /> </if> - <if expr="not pp_ifdef('toolkit_views') and is_posix and not is_macosx"> + <if expr="pp_ifdef('desktop_linux')"> <structure type="chrome_scaled_image" name="IDR_RESTORE" file="linux/linux_restore.png" /> <structure type="chrome_scaled_image" name="IDR_RESTORE_H" file="linux/linux_restore_hover.png" /> <structure type="chrome_scaled_image" name="IDR_RESTORE_P" file="linux/linux_restore_pressed.png" /> </if> - <if expr="pp_ifdef('toolkit_views')"> + <if expr="not pp_ifdef('desktop_linux') and pp_ifdef('toolkit_views')"> <structure type="chrome_scaled_image" name="IDR_RESTORE" file="restore.png" /> <structure type="chrome_scaled_image" name="IDR_RESTORE_H" file="restore_hover.png" /> <structure type="chrome_scaled_image" name="IDR_RESTORE_P" file="restore_pressed.png" /> @@ -338,7 +375,7 @@ <structure type="chrome_scaled_image" name="IDR_TEXTBUTTON_PRESSED_TOP_LEFT" file="common/textbutton_pressed_top_left.png" /> <structure type="chrome_scaled_image" name="IDR_TEXTBUTTON_PRESSED_TOP_RIGHT" file="common/textbutton_pressed_top_right.png" /> <structure type="chrome_scaled_image" name="IDR_THROBBER" file="throbber.png" /> - <if expr="is_macosx"> + <if expr="is_macosx or is_ios"> <structure type="chrome_scaled_image" name="IDR_TRAY_ATTENTION" file="mac/notification_tray_attention.png"/> <structure type="chrome_scaled_image" name="IDR_TRAY_ATTENTION_PRESSED" file="mac/notification_tray_attention_pressed.png"/> <structure type="chrome_scaled_image" name="IDR_TRAY_DO_NOT_DISTURB_ATTENTION" file="mac/notification_tray_do_not_disturb_attention.png"/> diff --git a/chromium/ui/shell_dialogs/android/shell_dialogs_jni_registrar.cc b/chromium/ui/shell_dialogs/android/shell_dialogs_jni_registrar.cc deleted file mode 100644 index d62392ab478..00000000000 --- a/chromium/ui/shell_dialogs/android/shell_dialogs_jni_registrar.cc +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 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 "ui/shell_dialogs/android/shell_dialogs_jni_registrar.h" - -#include "base/android/jni_android.h" -#include "base/android/jni_registrar.h" -#include "ui/shell_dialogs/select_file_dialog_android.h" - -namespace ui { -namespace shell_dialogs { - -static base::android::RegistrationMethod kUiRegisteredMethods[] = { - { "SelectFileDialog", ui::SelectFileDialogImpl::RegisterSelectFileDialog }, -}; - -bool RegisterJni(JNIEnv* env) { - return RegisterNativeMethods(env, kUiRegisteredMethods, - arraysize(kUiRegisteredMethods)); -} - -} // namespace shell_dialogs -} // namespace ui diff --git a/chromium/ui/shell_dialogs/android/shell_dialogs_jni_registrar.h b/chromium/ui/shell_dialogs/android/shell_dialogs_jni_registrar.h deleted file mode 100644 index 59750801540..00000000000 --- a/chromium/ui/shell_dialogs/android/shell_dialogs_jni_registrar.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 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. - -#ifndef UI_SHELL_DIALOGS_ANDROID_UI_SHELL_DIALOGS_JNI_REGISTRAR_H_ -#define UI_SHELL_DIALOGS_ANDROID_UI_SHELL_DIALOGS_JNI_REGISTRAR_H_ - -#include <jni.h> - -#include "ui/shell_dialogs/shell_dialogs_export.h" - -namespace ui { -namespace shell_dialogs { - -// Register all JNI bindings necessary for chrome. -SHELL_DIALOGS_EXPORT bool RegisterJni(JNIEnv* env); - -} // namespace shell_dialogs -} // namespace ui - -#endif // UI_SHELL_DIALOGS_ANDROID_UI_SHELL_DIALOGS_JNI_REGISTRAR_H_ diff --git a/chromium/ui/shell_dialogs/select_file_dialog_win.cc b/chromium/ui/shell_dialogs/select_file_dialog_win.cc index eff7a493c19..c028d22c7ae 100644 --- a/chromium/ui/shell_dialogs/select_file_dialog_win.cc +++ b/chromium/ui/shell_dialogs/select_file_dialog_win.cc @@ -414,7 +414,7 @@ class SelectFileDialogImpl : public ui::SelectFileDialog, ui::SelectFilePolicy* policy); // BaseShellDialog implementation: - virtual bool IsRunning(gfx::NativeWindow owning_hwnd) const OVERRIDE; + virtual bool IsRunning(gfx::NativeWindow owning_window) const OVERRIDE; virtual void ListenerDestroyed() OVERRIDE; protected: @@ -598,7 +598,7 @@ void SelectFileDialogImpl::SelectFileImpl( return; } } - HWND owner = owning_window + HWND owner = owning_window && owning_window->GetRootWindow() ? owning_window->GetRootWindow()->GetAcceleratedWidget() : NULL; #else HWND owner = owning_window; @@ -617,11 +617,13 @@ bool SelectFileDialogImpl::HasMultipleFileTypeChoicesImpl() { return has_multiple_file_type_choices_; } -bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow owning_hwnd) const { +bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow owning_window) const { #if defined(USE_AURA) - HWND owner = owning_hwnd->GetRootWindow()->GetAcceleratedWidget(); + if (!owning_window->GetRootWindow()) + return false; + HWND owner = owning_window->GetRootWindow()->GetAcceleratedWidget(); #else - HWND owner = owning_hwnd; + HWND owner = owning_window; #endif return listener_ && IsRunningDialogForOwner(owner); } diff --git a/chromium/ui/snapshot/OWNERS b/chromium/ui/snapshot/OWNERS new file mode 100644 index 00000000000..326ee949548 --- /dev/null +++ b/chromium/ui/snapshot/OWNERS @@ -0,0 +1,5 @@ +# Android +per-file *android*=bulach@chromium.org +per-file *android*=tedchoc@chromium.org +per-file *android*=yfriedman@chromium.org +per-file *android*=newt@chromium.org diff --git a/chromium/ui/snapshot/snapshot_android.cc b/chromium/ui/snapshot/snapshot_android.cc index 4e89c9da1ca..14c43ee9b46 100644 --- a/chromium/ui/snapshot/snapshot_android.cc +++ b/chromium/ui/snapshot/snapshot_android.cc @@ -4,22 +4,32 @@ #include "ui/snapshot/snapshot.h" +#include "ui/android/view_android.h" +#include "ui/android/window_android.h" +#include "ui/gfx/display.h" #include "ui/gfx/rect.h" +#include "ui/gfx/screen.h" namespace ui { bool GrabViewSnapshot(gfx::NativeView view, std::vector<unsigned char>* png_representation, const gfx::Rect& snapshot_bounds) { - // TODO(bajones): Implement Android snapshot functionality - return false; + return GrabWindowSnapshot( + view->GetWindowAndroid(), png_representation, snapshot_bounds); } bool GrabWindowSnapshot(gfx::NativeWindow window, std::vector<unsigned char>* png_representation, const gfx::Rect& snapshot_bounds) { - // TODO(bajones): Implement Android snapshot functionality - return false; + gfx::Display display = + gfx::Screen::GetNativeScreen()->GetPrimaryDisplay(); + gfx::Rect scaled_bounds = + gfx::ScaleToEnclosingRect(snapshot_bounds, + display.device_scale_factor()); + return window->GrabSnapshot( + scaled_bounds.x(), scaled_bounds.y(), scaled_bounds.width(), + scaled_bounds.height(), png_representation); } } // namespace ui diff --git a/chromium/ui/surface/accelerated_surface_win.cc b/chromium/ui/surface/accelerated_surface_win.cc index 3b86db01ad4..15d78c00ac3 100644 --- a/chromium/ui/surface/accelerated_surface_win.cc +++ b/chromium/ui/surface/accelerated_surface_win.cc @@ -8,8 +8,8 @@ #include <algorithm> #include "base/bind.h" -#include "base/bind_helpers.h" #include "base/callback.h" +#include "base/callback_helpers.h" #include "base/command_line.h" #include "base/debug/trace_event.h" #include "base/files/file_path.h" @@ -25,11 +25,11 @@ #include "media/base/video_frame.h" #include "media/base/video_util.h" #include "third_party/skia/include/core/SkBitmap.h" -#include "ui/base/latency_info.h" -#include "ui/base/win/dpi.h" -#include "ui/base/win/hwnd_util.h" #include "ui/base/win/shell.h" +#include "ui/events/latency_info.h" #include "ui/gfx/rect.h" +#include "ui/gfx/win/dpi.h" +#include "ui/gfx/win/hwnd_util.h" #include "ui/gl/gl_switches.h" #include "ui/surface/accelerated_surface_transformer_win.h" #include "ui/surface/d3d9_utils_win.h" @@ -332,12 +332,6 @@ void AcceleratedPresenterMap::RemovePresenter( scoped_refptr<AcceleratedPresenter> AcceleratedPresenterMap::GetPresenter( gfx::PluginWindowHandle window) { base::AutoLock locked(lock_); - -#if defined(USE_AURA) - if (!window) - return presenters_.begin()->second; -#endif - PresenterMap::iterator it = presenters_.find(window); if (it == presenters_.end()) return scoped_refptr<AcceleratedPresenter>(); @@ -672,13 +666,6 @@ void AcceleratedPresenter::ResetPresentThread( quantized_size_ = gfx::Size(); } -#if defined(USE_AURA) -void AcceleratedPresenter::SetNewTargetWindow(gfx::PluginWindowHandle window) { - window_ = window; - swap_chain_ = NULL; -} -#endif - AcceleratedPresenter::~AcceleratedPresenter() { } @@ -728,15 +715,16 @@ void AcceleratedPresenter::DoPresentAndAcknowledge( return; } +#if !defined(USE_AURA) // If the window is a different size than the swap chain that is being // presented then drop the frame. gfx::Size window_size = GetWindowSize(); bool size_mismatch = size != window_size; - if (ui::IsInHighDPIMode()) { + if (gfx::IsInHighDPIMode()) { // Check if the size mismatch is within allowable round off or truncation // error. - gfx::Size dip_size = ui::win::ScreenToDIPSize(window_size); - gfx::Size pixel_size = ui::win::DIPToScreenSize(dip_size); + gfx::Size dip_size = gfx::win::ScreenToDIPSize(window_size); + gfx::Size pixel_size = gfx::win::DIPToScreenSize(dip_size); size_mismatch = abs(window_size.width() - size.width()) > abs(window_size.width() - pixel_size.width()) || abs(window_size.height() - size.height()) > @@ -750,7 +738,7 @@ void AcceleratedPresenter::DoPresentAndAcknowledge( "windowheight", window_size.height()); return; } - +#endif // Round up size so the swap chain is not continuously resized with the // surface, which could lead to memory fragmentation. const int kRound = 64; diff --git a/chromium/ui/surface/accelerated_surface_win.h b/chromium/ui/surface/accelerated_surface_win.h index 357fff36733..7c4164b469b 100644 --- a/chromium/ui/surface/accelerated_surface_win.h +++ b/chromium/ui/surface/accelerated_surface_win.h @@ -14,7 +14,7 @@ #include "base/synchronization/waitable_event.h" #include "base/time/time.h" #include "base/win/scoped_comptr.h" -#include "ui/base/latency_info.h" +#include "ui/events/latency_info.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/size.h" #include "ui/surface/surface_export.h" @@ -89,12 +89,6 @@ class SURFACE_EXPORT AcceleratedPresenter // the given present thread. void ResetPresentThread(PresentThread* present_thread); -#if defined(USE_AURA) - // TODO(scottmg): This is a temporary hack until we have a two-worlds ash/aura - // separation. - void SetNewTargetWindow(gfx::PluginWindowHandle window); -#endif - private: friend class base::RefCountedThreadSafe<AcceleratedPresenter>; diff --git a/chromium/ui/surface/transport_dib.h b/chromium/ui/surface/transport_dib.h index 1d5410df25d..7ec7bb815f7 100644 --- a/chromium/ui/surface/transport_dib.h +++ b/chromium/ui/surface/transport_dib.h @@ -16,6 +16,7 @@ #include <windows.h> #elif defined(TOOLKIT_GTK) #include "ui/base/x/x11_util.h" +#include "ui/gfx/x/x11_types.h" #endif class SkCanvas; @@ -189,7 +190,7 @@ class SURFACE_EXPORT TransportDIB { #if defined(TOOLKIT_GTK) // Map the shared memory into the X server and return an id for the shared // segment. - XID MapToX(Display* connection); + XID MapToX(XDisplay* connection); void IncreaseInFlightCounter() { inflight_counter_++; } // Decreases the inflight counter, and deletes the transport DIB if it is @@ -211,7 +212,7 @@ class SURFACE_EXPORT TransportDIB { Id key_; // SysV shared memory id void* address_; // mapped address XSharedMemoryId x_shm_; // X id for the shared segment - Display* display_; // connection to the X server + XDisplay* display_; // connection to the X server size_t inflight_counter_; // How many requests to the X server are in flight bool detached_; // If true, delete the transport DIB when it is idle #else diff --git a/chromium/ui/surface/transport_dib_gtk.cc b/chromium/ui/surface/transport_dib_gtk.cc index 31f651328a0..61ec624c065 100644 --- a/chromium/ui/surface/transport_dib_gtk.cc +++ b/chromium/ui/surface/transport_dib_gtk.cc @@ -133,7 +133,7 @@ TransportDIB::Handle TransportDIB::handle() const { return key_.shmkey; } -XID TransportDIB::MapToX(Display* display) { +XID TransportDIB::MapToX(XDisplay* display) { if (!x_shm_) { x_shm_ = ui::AttachSharedMemory(display, key_.shmkey); display_ = display; diff --git a/chromium/ui/ui.gyp b/chromium/ui/ui.gyp index b1e288098f5..4716f6c9cd0 100644 --- a/chromium/ui/ui.gyp +++ b/chromium/ui/ui.gyp @@ -31,6 +31,8 @@ 'ui_resources', ], 'defines': [ + # TODO(sky): remove once gfx dependencies are corrected. + 'GFX_IMPLEMENTATION', 'UI_IMPLEMENTATION', ], # Export these dependencies since text_elider.h includes ICU headers. @@ -62,23 +64,7 @@ 'base/accessibility/accessible_text_utils.h', 'base/accessibility/accessible_view_state.cc', 'base/accessibility/accessible_view_state.h', - 'base/animation/animation.cc', - 'base/animation/animation.h', - 'base/animation/animation_container.cc', - 'base/animation/animation_container.h', - 'base/animation/animation_container_element.h', - 'base/animation/animation_container_observer.h', - 'base/animation/animation_delegate.h', - 'base/animation/linear_animation.cc', - 'base/animation/linear_animation.h', - 'base/animation/multi_animation.cc', - 'base/animation/multi_animation.h', - 'base/animation/slide_animation.cc', - 'base/animation/slide_animation.h', - 'base/animation/throb_animation.cc', - 'base/animation/throb_animation.h', - 'base/animation/tween.cc', - 'base/animation/tween.h', + 'base/base_window.cc', 'base/base_window.h', 'base/clipboard/clipboard.cc', 'base/clipboard/clipboard.h', @@ -99,6 +85,8 @@ 'base/clipboard/scoped_clipboard_writer.cc', 'base/clipboard/scoped_clipboard_writer.h', 'base/cocoa/animation_utils.h', + 'base/cocoa/appkit_utils.h', + 'base/cocoa/appkit_utils.mm', 'base/cocoa/base_view.h', 'base/cocoa/base_view.mm', 'base/cocoa/cocoa_event_utils.h', @@ -177,19 +165,6 @@ 'base/dragdrop/os_exchange_data_provider_aura.h', 'base/dragdrop/os_exchange_data_provider_win.cc', 'base/dragdrop/os_exchange_data_provider_win.h', - 'base/events/event.cc', - 'base/events/event.h', - 'base/events/event_constants.h', - 'base/events/event_conversion_gtk.cc', - 'base/events/event_conversion_gtk.h', - 'base/events/event_dispatcher.cc', - 'base/events/event_dispatcher.h', - 'base/events/event_handler.cc', - 'base/events/event_handler.h', - 'base/events/event_target.cc', - 'base/events/event_target.h', - 'base/events/event_utils.cc', - 'base/events/event_utils.h', 'base/gestures/gesture_configuration.cc', 'base/gestures/gesture_configuration.h', 'base/gestures/gesture_point.cc', @@ -227,26 +202,9 @@ 'base/gtk/gtk_windowing.h', 'base/gtk/owned_widget_gtk.cc', 'base/gtk/owned_widget_gtk.h', - 'base/gtk/scoped_gobject.h', 'base/gtk/scoped_region.cc', 'base/gtk/scoped_region.h', 'base/hit_test.h', - 'base/keycodes/keyboard_code_conversion.cc', - 'base/keycodes/keyboard_code_conversion.h', - 'base/keycodes/keyboard_code_conversion_android.cc', - 'base/keycodes/keyboard_code_conversion_android.h', - 'base/keycodes/keyboard_code_conversion_gtk.cc', - 'base/keycodes/keyboard_code_conversion_gtk.h', - 'base/keycodes/keyboard_code_conversion_mac.h', - 'base/keycodes/keyboard_code_conversion_mac.mm', - 'base/keycodes/keyboard_code_conversion_win.cc', - 'base/keycodes/keyboard_code_conversion_win.h', - 'base/keycodes/keyboard_code_conversion_x.cc', - 'base/keycodes/keyboard_code_conversion_x.h', - 'base/keycodes/keyboard_codes.h', - 'base/keycodes/usb_keycode_map.h', - 'base/latency_info.cc', - 'base/latency_info.h', 'base/l10n/l10n_font_util.cc', 'base/l10n/l10n_font_util.h', 'base/l10n/l10n_util.cc', @@ -256,6 +214,8 @@ 'base/l10n/l10n_util_collator.h', 'base/l10n/l10n_util_mac.h', 'base/l10n/l10n_util_mac.mm', + 'base/l10n/l10n_util_plurals.cc', + 'base/l10n/l10n_util_plurals.h', 'base/l10n/l10n_util_posix.cc', 'base/l10n/l10n_util_win.cc', 'base/l10n/l10n_util_win.h', @@ -287,22 +247,6 @@ 'base/models/tree_model.h', 'base/models/tree_node_iterator.h', 'base/models/tree_node_model.h', - 'base/ozone/evdev/key_event_converter_ozone.cc', - 'base/ozone/evdev/key_event_converter_ozone.h', - 'base/ozone/evdev/touch_event_converter_ozone.cc', - 'base/ozone/evdev/touch_event_converter_ozone.h', - 'base/ozone/event_converter_ozone.cc', - 'base/ozone/event_converter_ozone.h', - 'base/ozone/event_factory_delegate_ozone.h', - 'base/ozone/event_factory_ozone.cc', - 'base/ozone/event_factory_ozone.h', - 'base/ozone/events_ozone.cc', - 'base/ozone/surface_factory_ozone.cc', - 'base/ozone/surface_factory_ozone.h', - 'base/range/range.cc', - 'base/range/range.h', - 'base/range/range_mac.mm', - 'base/range/range_win.cc', 'base/resource/data_pack.cc', 'base/resource/data_pack.h', 'base/resource/resource_bundle.cc', @@ -317,12 +261,10 @@ 'base/resource/resource_data_dll_win.cc', 'base/resource/resource_data_dll_win.h', 'base/resource/resource_handle.h', + 'base/sequential_id_generator.cc', + 'base/sequential_id_generator.h', 'base/text/bytes_formatting.cc', 'base/text/bytes_formatting.h', - 'base/text/text_elider.cc', - 'base/text/text_elider.h', - 'base/text/utf16_indexing.cc', - 'base/text/utf16_indexing.h', 'base/theme_provider.cc', 'base/theme_provider.h', 'base/touch/touch_device.cc', @@ -353,8 +295,6 @@ 'base/win/accessibility_misc_utils.cc', 'base/win/accessibility_misc_utils.h', 'base/win/atl_module.h', - 'base/win/dpi.cc', - 'base/win/dpi.h', 'base/win/events_win.cc', 'base/win/extra_sdk_defines.h', 'base/win/foreground_helper.cc', @@ -363,23 +303,16 @@ 'base/win/hidden_window.h', 'base/win/hwnd_subclass.cc', 'base/win/hwnd_subclass.h', - 'base/win/hwnd_util.cc', - 'base/win/hwnd_util.h', 'base/win/message_box_win.cc', 'base/win/message_box_win.h', 'base/win/mouse_wheel_util.cc', 'base/win/mouse_wheel_util.h', 'base/win/scoped_ole_initializer.cc', 'base/win/scoped_ole_initializer.h', - 'base/win/scoped_set_map_mode.h', 'base/win/shell.cc', 'base/win/shell.h', - 'base/win/singleton_hwnd.cc', - 'base/win/singleton_hwnd.h', 'base/win/touch_input.cc', 'base/win/touch_input.h', - 'base/win/window_impl.cc', - 'base/win/window_impl.h', 'base/window_open_disposition.cc', 'base/window_open_disposition.h', 'base/work_area_watcher_observer.h', @@ -403,13 +336,70 @@ 'base/x/work_area_watcher_x.h', 'base/x/x11_atom_cache.cc', 'base/x/x11_atom_cache.h', + 'base/x/x11_error_tracker.cc', + 'base/x/x11_error_tracker.h', + 'base/x/x11_error_tracker_gtk.cc', 'base/x/x11_util.cc', 'base/x/x11_util.h', 'base/x/x11_util_internal.h', + 'events/event.cc', + 'events/event.h', + 'events/event_constants.h', + 'events/event_dispatcher.cc', + 'events/event_dispatcher.h', + 'events/event_handler.cc', + 'events/event_handler.h', + 'events/event_target.cc', + 'events/event_target.h', + 'events/event_utils.cc', + 'events/event_utils.h', + 'events/events_export.h', + 'events/keycodes/keyboard_code_conversion.cc', + 'events/keycodes/keyboard_code_conversion.h', + 'events/keycodes/keyboard_code_conversion_android.cc', + 'events/keycodes/keyboard_code_conversion_android.h', + 'events/keycodes/keyboard_code_conversion_gtk.cc', + 'events/keycodes/keyboard_code_conversion_gtk.h', + 'events/keycodes/keyboard_code_conversion_mac.h', + 'events/keycodes/keyboard_code_conversion_mac.mm', + 'events/keycodes/keyboard_code_conversion_win.cc', + 'events/keycodes/keyboard_code_conversion_win.h', + 'events/keycodes/keyboard_code_conversion_x.cc', + 'events/keycodes/keyboard_code_conversion_x.h', + 'events/keycodes/keyboard_codes.h', + 'events/latency_info.cc', + 'events/latency_info.h', + 'events/ozone/evdev/key_event_converter_ozone.cc', + 'events/ozone/evdev/key_event_converter_ozone.h', + 'events/ozone/evdev/touch_event_converter_ozone.cc', + 'events/ozone/evdev/touch_event_converter_ozone.h', + 'events/ozone/event_converter_ozone.cc', + 'events/ozone/event_converter_ozone.h', + 'events/ozone/event_factory_delegate_ozone.h', + 'events/ozone/event_factory_ozone.cc', + 'events/ozone/event_factory_ozone.h', + 'events/ozone/events_ozone.cc', 'gfx/android/device_display_info.cc', 'gfx/android/device_display_info.h', 'gfx/android/java_bitmap.cc', 'gfx/android/java_bitmap.h', + 'gfx/animation/animation.cc', + 'gfx/animation/animation.h', + 'gfx/animation/animation_container.cc', + 'gfx/animation/animation_container.h', + 'gfx/animation/animation_container_element.h', + 'gfx/animation/animation_container_observer.h', + 'gfx/animation/animation_delegate.h', + 'gfx/animation/linear_animation.cc', + 'gfx/animation/linear_animation.h', + 'gfx/animation/multi_animation.cc', + 'gfx/animation/multi_animation.h', + 'gfx/animation/slide_animation.cc', + 'gfx/animation/slide_animation.h', + 'gfx/animation/throb_animation.cc', + 'gfx/animation/throb_animation.h', + 'gfx/animation/tween.cc', + 'gfx/animation/tween.h', 'gfx/blit.cc', 'gfx/blit.h', 'gfx/box_f.cc', @@ -418,13 +408,12 @@ 'gfx/canvas.cc', 'gfx/canvas.h', 'gfx/canvas_android.cc', - 'gfx/canvas_mac.mm', + 'gfx/canvas_paint_gtk.cc', 'gfx/canvas_paint_gtk.h', 'gfx/canvas_paint_mac.h', - 'gfx/canvas_paint_win.h', - 'gfx/canvas_paint_gtk.cc', 'gfx/canvas_paint_mac.mm', 'gfx/canvas_paint_win.cc', + 'gfx/canvas_paint_win.h', 'gfx/canvas_skia.cc', 'gfx/canvas_skia_paint.h', 'gfx/codec/jpeg_codec.cc', @@ -456,6 +445,7 @@ 'gfx/font_render_params_linux.h', 'gfx/font_smoothing_win.cc', 'gfx/font_smoothing_win.h', + 'gfx/gfx_export.h', 'gfx/gfx_paths.cc', 'gfx/gfx_paths.h', 'gfx/gpu_memory_buffer.cc', @@ -495,6 +485,8 @@ 'gfx/matrix3_f.cc', 'gfx/matrix3_f.h', 'gfx/native_widget_types.h', + 'gfx/ozone/surface_factory_ozone.cc', + 'gfx/ozone/surface_factory_ozone.h', 'gfx/pango_util.cc', 'gfx/pango_util.h', 'gfx/path.cc', @@ -526,6 +518,10 @@ 'gfx/point_f.h', 'gfx/quad_f.cc', 'gfx/quad_f.h', + 'gfx/range/range.cc', + 'gfx/range/range.h', + 'gfx/range/range_mac.mm', + 'gfx/range/range_win.cc', 'gfx/rect.cc', 'gfx/rect.h', 'gfx/rect_base.h', @@ -581,12 +577,19 @@ 'gfx/sys_color_change_listener.cc', 'gfx/sys_color_change_listener.h', 'gfx/text_constants.h', + 'gfx/text_elider.cc', + 'gfx/text_elider.h', 'gfx/text_utils.cc', 'gfx/text_utils.h', + 'gfx/text_utils_android.cc', + 'gfx/text_utils_ios.mm', + 'gfx/text_utils_skia.cc', 'gfx/transform.cc', 'gfx/transform.h', 'gfx/transform_util.cc', 'gfx/transform_util.h', + 'gfx/utf16_indexing.cc', + 'gfx/utf16_indexing.h', 'gfx/vector2d.cc', 'gfx/vector2d.h', 'gfx/vector2d_conversions.cc', @@ -595,6 +598,17 @@ 'gfx/vector2d_f.h', 'gfx/vector3d_f.cc', 'gfx/vector3d_f.h', + 'gfx/win/dpi.cc', + 'gfx/win/dpi.h', + 'gfx/win/hwnd_util.cc', + 'gfx/win/hwnd_util.h', + 'gfx/win/scoped_set_map_mode.h', + 'gfx/win/singleton_hwnd.cc', + 'gfx/win/singleton_hwnd.h', + 'gfx/win/window_impl.cc', + 'gfx/win/window_impl.h', + 'gfx/x/x11_types.cc', + 'gfx/x/x11_types.h', 'webui/jstemplate_builder.cc', 'webui/jstemplate_builder.h', 'webui/web_ui_util.cc', @@ -622,13 +636,12 @@ ['include', '_ios\\.(cc|mm)$'], ['include', '(^|/)ios/'], ['include', '^gfx/'], + ['include', '^gfx/animation/'], ['exclude', '^gfx/codec/jpeg_codec\\.cc$'], - ['include', '^base/animation/'], + ['include', '^gfx/range/'], ['include', '^base/l10n/'], ['include', '^base/layout'], - ['include', '^base/range/'], ['include', '^base/resource/'], - ['include', '^base/text/text_elider\\.'], ['include', '^base/ui_base_'], ], 'link_settings': { @@ -642,7 +655,6 @@ ['use_canvas_skia==1', { 'sources!': [ 'gfx/canvas_android.cc', - 'gfx/canvas_mac.mm', ], }, { # use_canvas_skia!=1 'sources!': [ @@ -740,10 +752,16 @@ 'gfx/gtk_native_view_id_manager.h', 'gfx/gtk_preserve_window.cc', 'gfx/gtk_preserve_window.h', + 'gfx/gdk_compat.h', + 'gfx/gtk_compat.h', 'gfx/gtk_util.cc', 'gfx/gtk_util.h', 'gfx/image/cairo_cached_surface.cc', 'gfx/image/cairo_cached_surface.h', + 'gfx/scoped_gobject.h', + ], + 'sources!': [ + 'base/x/x11_error_tracker.cc', ], }], ['chromeos==1 or (use_aura==1 and OS=="linux" and use_x11==0)', { @@ -857,7 +875,7 @@ ], }, { # use_x11==0 'sources/': [ - ['exclude', 'base/keycodes/keyboard_code_conversion_x.*'], + ['exclude', 'events/keycodes/keyboard_code_conversion_x.*'], ['exclude', 'base/x/*'], ], }], @@ -870,22 +888,37 @@ }], ['use_qt==0 and toolkit_views==0', { 'sources!': [ - 'base/events/event.cc', - 'base/events/event.h', - 'base/events/event_dispatcher.cc', - 'base/events/event_dispatcher.h', - 'base/events/event_handler.cc', - 'base/events/event_handler.h', - 'base/events/event_target.cc', - 'base/events/event_target.h', 'base/x/events_x.cc', + 'events/event.cc', + 'events/event.h', + 'events/event_dispatcher.cc', + 'events/event_dispatcher.h', + 'events/event_handler.cc', + 'events/event_handler.h', + 'events/event_target.cc', + 'events/event_target.h', ], }], ['OS=="android"', { 'sources!': [ + 'base/accessibility/accessible_text_utils.cc', + 'base/accessibility/accessible_view_state.cc', + 'base/default_theme_provider.cc', 'base/dragdrop/drag_utils.cc', 'base/dragdrop/drag_utils.h', + 'events/event_utils.cc', + 'events/keycodes/keyboard_code_conversion.cc', + 'base/l10n/l10n_font_util.cc', + 'base/models/button_menu_item_model.cc', + 'base/models/dialog_model.cc', + 'base/theme_provider.cc', 'base/touch/touch_device.cc', + 'base/touch/touch_editing_controller.cc', + 'base/ui_base_types.cc', + 'gfx/animation/throb_animation.cc', + 'gfx/display_observer.cc', + 'gfx/path.cc', + 'gfx/selection_model.cc', ], 'dependencies': [ 'ui_jni_headers', @@ -908,6 +941,7 @@ 'sources!': [ 'gfx/render_text.cc', 'gfx/render_text.h', + 'gfx/text_utils_skia.cc', ], }], ['OS=="linux"', { @@ -931,6 +965,18 @@ '<(SHARED_INTERMEDIATE_DIR)/ui/ui_resources', ] } + }, + { + 'target_name': 'keycode_converter', + 'type': 'static_library', + 'dependencies': [ + '../base/base.gyp:base', + ], + 'sources': [ + 'base/keycodes/keycode_converter.cc', + 'base/keycodes/keycode_converter.h', + 'base/keycodes/keycode_converter_data.h', + ], } ], 'conditions': [ diff --git a/chromium/ui/ui_unittests.gypi b/chromium/ui/ui_unittests.gypi index e62af9376f8..ac73bfef4ff 100644 --- a/chromium/ui/ui_unittests.gypi +++ b/chromium/ui/ui_unittests.gypi @@ -82,6 +82,7 @@ '../third_party/libpng/libpng.gyp:libpng', '../url/url.gyp:url_lib', 'base/strings/ui_strings.gyp:ui_strings', + 'keycode_converter', 'run_ui_unittests', 'shell_dialogs', 'ui', @@ -91,23 +92,19 @@ # iOS uses a small subset of ui. common_sources are the only files that # are built on iOS. 'common_sources' : [ - 'base/animation/animation_container_unittest.cc', - 'base/animation/animation_unittest.cc', - 'base/animation/multi_animation_unittest.cc', - 'base/animation/slide_animation_unittest.cc', 'base/layout_unittest.cc', 'base/l10n/l10n_util_mac_unittest.mm', 'base/l10n/l10n_util_unittest.cc', 'base/l10n/l10n_util_win_unittest.cc', 'base/l10n/time_format_unittest.cc', 'base/models/tree_node_iterator_unittest.cc', - 'base/range/range_mac_unittest.mm', - 'base/range/range_unittest.cc', - 'base/range/range_win_unittest.cc', 'base/resource/data_pack_literal.cc', 'base/resource/data_pack_unittest.cc', 'base/resource/resource_bundle_unittest.cc', - 'base/text/text_elider_unittest.cc', + 'gfx/animation/animation_container_unittest.cc', + 'gfx/animation/animation_unittest.cc', + 'gfx/animation/multi_animation_unittest.cc', + 'gfx/animation/slide_animation_unittest.cc', 'gfx/box_unittest.cc', 'gfx/codec/png_codec_unittest.cc', 'gfx/color_utils_unittest.cc', @@ -125,12 +122,16 @@ 'gfx/point_unittest.cc', 'gfx/point3_unittest.cc', 'gfx/quad_unittest.cc', + 'gfx/range/range_mac_unittest.mm', + 'gfx/range/range_unittest.cc', + 'gfx/range/range_win_unittest.cc', 'gfx/rect_unittest.cc', 'gfx/safe_integer_conversions_unittest.cc', 'gfx/screen_unittest.cc', 'gfx/shadow_value_unittest.cc', 'gfx/size_unittest.cc', 'gfx/skbitmap_operations_unittest.cc', + 'gfx/text_elider_unittest.cc', 'gfx/text_utils_unittest.cc', 'gfx/vector2d_unittest.cc', 'gfx/vector3d_unittest.cc', @@ -152,23 +153,25 @@ 'base/cocoa/menu_controller_unittest.mm', 'base/cocoa/nsgraphics_context_additions_unittest.mm', 'base/cocoa/tracking_area_unittest.mm', - 'base/events/event_dispatcher_unittest.cc', - 'base/events/event_unittest.cc', + 'base/dragdrop/os_exchange_data_provider_aurax11_unittest.cc', 'base/gtk/gtk_expanded_container_unittest.cc', 'base/gtk/gtk_im_context_util_unittest.cc', - 'base/keycodes/usb_keycode_map_unittest.cc', - 'base/latency_info_unittest.cc', + 'base/keycodes/keycode_converter_unittest.cc', 'base/models/list_model_unittest.cc', 'base/models/list_selection_model_unittest.cc', 'base/models/tree_node_model_unittest.cc', - 'base/ozone/evdev/touch_event_converter_ozone_unittest.cc', + 'base/sequential_id_generator_unittest.cc', 'base/test/data/resource.h', 'base/text/bytes_formatting_unittest.cc', - 'base/text/utf16_indexing_unittest.cc', 'base/view_prop_unittest.cc', + 'events/event_dispatcher_unittest.cc', + 'events/event_unittest.cc', + 'events/latency_info_unittest.cc', + 'events/ozone/evdev/touch_event_converter_ozone_unittest.cc', 'gfx/blit_unittest.cc', 'gfx/break_list_unittest.cc', 'gfx/canvas_unittest.cc', + 'gfx/canvas_unittest_mac.mm', 'gfx/codec/jpeg_codec_unittest.cc', 'gfx/color_analysis_unittest.cc', 'gfx/font_list_unittest.cc', @@ -177,6 +180,7 @@ 'gfx/platform_font_mac_unittest.mm', 'gfx/render_text_unittest.cc', 'gfx/transform_util_unittest.cc', + 'gfx/utf16_indexing_unittest.cc', 'shell_dialogs/select_file_dialog_win_unittest.cc', 'webui/web_ui_util_unittest.cc', ], @@ -311,8 +315,8 @@ ], }, { 'sources!': [ - 'base/events/event_dispatcher_unittest.cc', - 'base/events/event_unittest.cc', + 'events/event_dispatcher_unittest.cc', + 'events/event_unittest.cc', ], }], ['use_aura==1', { @@ -322,6 +326,11 @@ 'gfx/screen_unittest.cc', ], }], + ['chromeos==1', { + 'sources!': [ + 'base/dragdrop/os_exchange_data_provider_aurax11_unittest.cc', + ], + }], ], 'target_conditions': [ ['OS == "ios"', { diff --git a/chromium/ui/ui_unittests.isolate b/chromium/ui/ui_unittests.isolate index 35f732b96ba..55ce04a9d47 100644 --- a/chromium/ui/ui_unittests.isolate +++ b/chromium/ui/ui_unittests.isolate @@ -7,7 +7,6 @@ 'variables': { 'isolate_dependency_tracked': [ 'base/test/data/data_pack_unittest/truncated-header.pak', - '<(PRODUCT_DIR)/chrome.pak', '<(PRODUCT_DIR)/locales/en-US.pak', ], }, diff --git a/chromium/ui/views/accessibility/native_view_accessibility.cc b/chromium/ui/views/accessibility/native_view_accessibility.cc index d94f05a0c0c..577ecfa41c2 100644 --- a/chromium/ui/views/accessibility/native_view_accessibility.cc +++ b/chromium/ui/views/accessibility/native_view_accessibility.cc @@ -29,11 +29,11 @@ void NativeViewAccessibility::Destroy() { #if !defined(OS_WIN) // static -void NativeViewAccessibility::RegisterWebView(AccessibleWebView* web_view) { +void NativeViewAccessibility::RegisterWebView(View* web_view) { } // static -void NativeViewAccessibility::UnregisterWebView(AccessibleWebView* web_view) { +void NativeViewAccessibility::UnregisterWebView(View* web_view) { } #endif diff --git a/chromium/ui/views/accessibility/native_view_accessibility.h b/chromium/ui/views/accessibility/native_view_accessibility.h index 688f34cc64e..2fc4c4423b6 100644 --- a/chromium/ui/views/accessibility/native_view_accessibility.h +++ b/chromium/ui/views/accessibility/native_view_accessibility.h @@ -13,13 +13,6 @@ namespace views { class View; -class AccessibleWebView { - public: - virtual gfx::NativeViewAccessible AccessibleObjectFromChildId(long child_id) - = 0; - virtual View* AsView() = 0; -}; - class VIEWS_EXPORT NativeViewAccessibility { public: static NativeViewAccessibility* Create(View* view); @@ -33,9 +26,11 @@ class VIEWS_EXPORT NativeViewAccessibility { // use reference counting. virtual void Destroy(); - static void RegisterWebView(AccessibleWebView* web_view); - - static void UnregisterWebView(AccessibleWebView* web_view); + // WebViews need to be registered because they implement their own + // tree of accessibility objects, and we need to check them when + // mapping a child id to a NativeViewAccessible. + static void RegisterWebView(View* web_view); + static void UnregisterWebView(View* web_view); protected: NativeViewAccessibility(); diff --git a/chromium/ui/views/accessibility/native_view_accessibility_win.cc b/chromium/ui/views/accessibility/native_view_accessibility_win.cc index 279c99d3d29..7aa92a2a13c 100644 --- a/chromium/ui/views/accessibility/native_view_accessibility_win.cc +++ b/chromium/ui/views/accessibility/native_view_accessibility_win.cc @@ -11,6 +11,8 @@ #include <vector> #include "base/memory/singleton.h" +#include "base/strings/utf_string_conversions.h" +#include "base/win/scoped_comptr.h" #include "base/win/windows_version.h" #include "third_party/iaccessible2/ia2_api_all.h" #include "ui/base/accessibility/accessible_text_utils.h" @@ -21,6 +23,7 @@ #include "ui/views/controls/button/custom_button.h" #include "ui/views/focus/focus_manager.h" #include "ui/views/focus/view_storage.h" +#include "ui/views/widget/widget.h" #include "ui/views/win/hwnd_util.h" using ui::AccessibilityTypes; @@ -32,9 +35,9 @@ class AccessibleWebViewRegistry { public: static AccessibleWebViewRegistry* GetInstance(); - void RegisterWebView(AccessibleWebView* web_view); + void RegisterWebView(View* web_view); - void UnregisterWebView(AccessibleWebView* web_view); + void UnregisterWebView(View* web_view); // Given the view that received the request for the accessible // id in |top_view|, and the child id requested, return the native @@ -42,40 +45,62 @@ class AccessibleWebViewRegistry { // |top_view|'s view hierarchy, if any. IAccessible* GetAccessibleFromWebView(View* top_view, long child_id); + // The system uses IAccessible APIs for many purposes, but only + // assistive technology like screen readers uses IAccessible2. + // Call this method to note that the IAccessible2 interface was queried and + // that WebViews should be proactively notified that this interface will be + // used. If this is enabled for the first time, this will explicitly call + // QueryService with an argument of IAccessible2 on all WebViews, otherwise + // it will just do it from now on. + void EnableIAccessible2Support(); + private: friend struct DefaultSingletonTraits<AccessibleWebViewRegistry>; AccessibleWebViewRegistry(); ~AccessibleWebViewRegistry() {} + IAccessible* AccessibleObjectFromChildId(View* web_view, long child_id); + + void QueryIAccessible2Interface(View* web_view); + // Set of all web views. We check whether each one is contained in a // top view dynamically rather than keeping track of a map. - std::set<AccessibleWebView*> web_views_; + std::set<View*> web_views_; // The most recent top view used in a call to GetAccessibleFromWebView. View* last_top_view_; // The most recent web view where an accessible object was found, // corresponding to |last_top_view_|. - AccessibleWebView* last_web_view_; + View* last_web_view_; + + // If IAccessible2 support is enabled, we query the IAccessible2 interface + // of WebViews proactively when they're registered, so that they are + // aware that they need to support this interface. + bool iaccessible2_support_enabled_; DISALLOW_COPY_AND_ASSIGN(AccessibleWebViewRegistry); }; AccessibleWebViewRegistry::AccessibleWebViewRegistry() : last_top_view_(NULL), - last_web_view_(NULL) { + last_web_view_(NULL), + iaccessible2_support_enabled_(false) { } AccessibleWebViewRegistry* AccessibleWebViewRegistry::GetInstance() { return Singleton<AccessibleWebViewRegistry>::get(); } -void AccessibleWebViewRegistry::RegisterWebView(AccessibleWebView* web_view) { +void AccessibleWebViewRegistry::RegisterWebView(View* web_view) { DCHECK(web_views_.find(web_view) == web_views_.end()); web_views_.insert(web_view); + + if (iaccessible2_support_enabled_) + QueryIAccessible2Interface(web_view); } -void AccessibleWebViewRegistry::UnregisterWebView(AccessibleWebView* web_view) { +void AccessibleWebViewRegistry::UnregisterWebView(View* web_view) { DCHECK(web_views_.find(web_view) != web_views_.end()); web_views_.erase(web_view); if (last_web_view_ == web_view) { @@ -91,7 +116,7 @@ IAccessible* AccessibleWebViewRegistry::GetAccessibleFromWebView( // sent the last one. if (last_top_view_ == top_view) { IAccessible* accessible = - last_web_view_->AccessibleObjectFromChildId(child_id); + AccessibleObjectFromChildId(last_web_view_, child_id); if (accessible) return accessible; } @@ -100,21 +125,65 @@ IAccessible* AccessibleWebViewRegistry::GetAccessibleFromWebView( // of this view where the event was posted - and if so, see if it owns // an accessible object with that child id. If so, save the view to speed // up the next notification. - for (std::set<AccessibleWebView*>::iterator iter = web_views_.begin(); + for (std::set<View*>::iterator iter = web_views_.begin(); iter != web_views_.end(); ++iter) { - AccessibleWebView* web_view = *iter; - if (!top_view->Contains(web_view->AsView())) + View* web_view = *iter; + if (top_view == web_view || !top_view->Contains(web_view)) continue; - IAccessible* accessible = web_view->AccessibleObjectFromChildId(child_id); + IAccessible* accessible = AccessibleObjectFromChildId(web_view, child_id); if (accessible) { last_top_view_ = top_view; last_web_view_ = web_view; return accessible; } } + + return NULL; +} + +void AccessibleWebViewRegistry::EnableIAccessible2Support() { + if (iaccessible2_support_enabled_) + return; + iaccessible2_support_enabled_ = true; + for (std::set<View*>::iterator iter = web_views_.begin(); + iter != web_views_.end(); ++iter) { + QueryIAccessible2Interface(*iter); + } +} + +IAccessible* AccessibleWebViewRegistry::AccessibleObjectFromChildId( + View* web_view, + long child_id) { + IAccessible* web_view_accessible = web_view->GetNativeViewAccessible(); + if (web_view_accessible == NULL) + return NULL; + + VARIANT var_child; + var_child.vt = VT_I4; + var_child.lVal = child_id; + IAccessible* result = NULL; + if (S_OK == web_view_accessible->get_accChild( + var_child, reinterpret_cast<IDispatch**>(&result))) { + return result; + } + return NULL; } +void AccessibleWebViewRegistry::QueryIAccessible2Interface(View* web_view) { + IAccessible* web_view_accessible = web_view->GetNativeViewAccessible(); + if (!web_view_accessible) + return; + + base::win::ScopedComPtr<IServiceProvider> service_provider; + if (S_OK != web_view_accessible->QueryInterface(service_provider.Receive())) + return; + base::win::ScopedComPtr<IAccessible2> iaccessible2; + service_provider->QueryService( + IID_IAccessible, IID_IAccessible2, + reinterpret_cast<void**>(iaccessible2.Receive())); +} + } // anonymous namespace // static @@ -179,7 +248,6 @@ void NativeViewAccessibilityWin::Destroy() { Release(); } -// TODO(ctguil): Handle case where child View is not contained by parent. STDMETHODIMP NativeViewAccessibilityWin::accHitTest( LONG x_left, LONG y_top, VARIANT* child) { if (!child) @@ -188,25 +256,71 @@ STDMETHODIMP NativeViewAccessibilityWin::accHitTest( if (!view_) return E_FAIL; + // If this is a root view, our widget might have child widgets. + // Search child widgets first, since they're on top in the z-order. + if (view_->GetWidget()->GetRootView() == view_) { + std::vector<Widget*> child_widgets; + PopulateChildWidgetVector(&child_widgets); + for (size_t i = 0; i < child_widgets.size(); ++i) { + Widget* child_widget = child_widgets[i]; + IAccessible* child_accessible = + child_widget->GetRootView()->GetNativeViewAccessible(); + HRESULT result = child_accessible->accHitTest(x_left, y_top, child); + if (result == S_OK) + return result; + } + } + gfx::Point point(x_left, y_top); View::ConvertPointToTarget(NULL, view_, &point); + // If the point is not inside this view, return false. if (!view_->HitTestPoint(point)) { - // If containing parent is not hit, return with failure. child->vt = VT_EMPTY; return S_FALSE; } - View* view = view_->GetEventHandlerForPoint(point); - if (view == view_) { - // No child hit, return parent id. - child->vt = VT_I4; - child->lVal = CHILDID_SELF; - } else { - child->vt = VT_DISPATCH; - child->pdispVal = view->GetNativeViewAccessible(); - child->pdispVal->AddRef(); + // Check if the point is within any of the immediate children of this + // view. + View* hit_child_view = NULL; + for (int i = view_->child_count() - 1; i >= 0; --i) { + View* child_view = view_->child_at(i); + if (!child_view->visible()) + continue; + + gfx::Point point_in_child_coords(point); + view_->ConvertPointToTarget(view_, child_view, &point_in_child_coords); + if (child_view->HitTestPoint(point_in_child_coords)) { + hit_child_view = child_view; + break; + } } + + // If the point was within one of this view's immediate children, + // call accHitTest recursively on that child's native view accessible - + // which may be a recursive call to this function or it may be overridden, + // for example in the case of a WebView. + if (hit_child_view) { + HRESULT result = hit_child_view->GetNativeViewAccessible()->accHitTest( + x_left, y_top, child); + + // If the recursive call returned CHILDID_SELF, we have to convert that + // into a VT_DISPATCH for the return value to this call. + if (S_OK == result && child->vt == VT_I4 && child->lVal == CHILDID_SELF) { + child->vt = VT_DISPATCH; + child->pdispVal = hit_child_view->GetNativeViewAccessible(); + // Always increment ref when returning a reference to a COM object. + child->pdispVal->AddRef(); + } + return result; + } + + // This object is the best match, so return CHILDID_SELF. It's tempting to + // simplify the logic and use VT_DISPATCH everywhere, but the Windows + // call AccessibleObjectFromPoint will keep calling accHitTest until some + // object returns CHILDID_SELF. + child->vt = VT_I4; + child->lVal = CHILDID_SELF; return S_OK; } @@ -357,16 +471,37 @@ STDMETHODIMP NativeViewAccessibilityWin::get_accChild(VARIANT var_child, return S_OK; } + // If this is a root view, our widget might have child widgets. Include + std::vector<Widget*> child_widgets; + if (view_->GetWidget()->GetRootView() == view_) + PopulateChildWidgetVector(&child_widgets); + int child_widget_count = static_cast<int>(child_widgets.size()); + View* child_view = NULL; if (child_id > 0) { // Positive child ids are a 1-based child index, used by clients // that want to enumerate all immediate children. int child_id_as_index = child_id - 1; - if (child_id_as_index < view_->child_count()) + if (child_id_as_index < view_->child_count()) { child_view = view_->child_at(child_id_as_index); + } else if (child_id_as_index < view_->child_count() + child_widget_count) { + Widget* child_widget = + child_widgets[child_id_as_index - view_->child_count()]; + child_view = child_widget->GetRootView(); + } } else { - // Negative child ids can be used to map to any descendant; - // we map child ids to a view storage id that can refer to a + // Negative child ids can be used to map to any descendant. + // Check child widget first. + for (int i = 0; i < child_widget_count; i++) { + Widget* child_widget = child_widgets[i]; + IAccessible* child_accessible = + child_widget->GetRootView()->GetNativeViewAccessible(); + HRESULT result = child_accessible->get_accChild(var_child, disp_child); + if (result == S_OK) + return result; + } + + // We map child ids to a view storage id that can refer to a // specific view (if that view still exists). int view_storage_id_index = base::win::kFirstViewsAccessibilityId - child_id; @@ -378,10 +513,8 @@ STDMETHODIMP NativeViewAccessibilityWin::get_accChild(VARIANT var_child, } else { *disp_child = AccessibleWebViewRegistry::GetInstance()-> GetAccessibleFromWebView(view_, child_id); - if (*disp_child) { - (*disp_child)->AddRef(); + if (*disp_child) return S_OK; - } } } @@ -404,6 +537,15 @@ STDMETHODIMP NativeViewAccessibilityWin::get_accChildCount(LONG* child_count) { return E_FAIL; *child_count = view_->child_count(); + + // If this is a root view, our widget might have child widgets. Include + // them, too. + if (view_->GetWidget()->GetRootView() == view_) { + std::vector<Widget*> child_widgets; + PopulateChildWidgetVector(&child_widgets); + *child_count += child_widgets.size(); + } + return S_OK; } @@ -929,6 +1071,9 @@ STDMETHODIMP NativeViewAccessibilityWin::QueryService( if (!view_) return E_FAIL; + if (riid == IID_IAccessible2) + AccessibleWebViewRegistry::GetInstance()->EnableIAccessible2Support(); + if (guidService == IID_IAccessible || guidService == IID_IAccessible2 || guidService == IID_IAccessibleText) { @@ -996,11 +1141,11 @@ STDMETHODIMP NativeViewAccessibilityWin::GetPropertyValue(PROPERTYID id, // Static methods. // -void NativeViewAccessibility::RegisterWebView(AccessibleWebView* web_view) { +void NativeViewAccessibility::RegisterWebView(View* web_view) { AccessibleWebViewRegistry::GetInstance()->RegisterWebView(web_view); } -void NativeViewAccessibility::UnregisterWebView(AccessibleWebView* web_view) { +void NativeViewAccessibility::UnregisterWebView(View* web_view) { AccessibleWebViewRegistry::GetInstance()->UnregisterWebView(web_view); } @@ -1244,4 +1389,26 @@ LONG NativeViewAccessibilityWin::FindBoundary( text, line_breaks, boundary, start_offset, direction); } +void NativeViewAccessibilityWin::PopulateChildWidgetVector( + std::vector<Widget*>* result_child_widgets) { + const Widget* widget = view()->GetWidget(); + std::set<Widget*> child_widgets; + Widget::GetAllChildWidgets(widget->GetNativeView(), &child_widgets); + Widget::GetAllOwnedWidgets(widget->GetNativeView(), &child_widgets); + for (std::set<Widget*>::const_iterator iter = child_widgets.begin(); + iter != child_widgets.end(); ++iter) { + Widget* child_widget = *iter; + if (child_widget == widget) + continue; + + if (!child_widget->IsVisible()) + continue; + + if (widget->GetNativeWindowProperty(kWidgetNativeViewHostKey)) + continue; + + result_child_widgets->push_back(child_widget); + } +} + } // namespace views diff --git a/chromium/ui/views/accessibility/native_view_accessibility_win.h b/chromium/ui/views/accessibility/native_view_accessibility_win.h index e616551b968..83d03dbe5d8 100644 --- a/chromium/ui/views/accessibility/native_view_accessibility_win.h +++ b/chromium/ui/views/accessibility/native_view_accessibility_win.h @@ -69,7 +69,7 @@ NativeViewAccessibilityWin // Supported IAccessible methods. // Retrieves the child element or child object at a given point on the screen. - STDMETHODIMP accHitTest(LONG x_left, LONG y_top, VARIANT* child); + virtual STDMETHODIMP accHitTest(LONG x_left, LONG y_top, VARIANT* child); // Performs the object's default action. STDMETHODIMP accDoDefaultAction(VARIANT var_id); @@ -85,10 +85,10 @@ NativeViewAccessibilityWin STDMETHODIMP accNavigate(LONG nav_dir, VARIANT start, VARIANT* end); // Retrieves an IDispatch interface pointer for the specified child. - STDMETHODIMP get_accChild(VARIANT var_child, IDispatch** disp_child); + virtual STDMETHODIMP get_accChild(VARIANT var_child, IDispatch** disp_child); // Retrieves the number of accessible children. - STDMETHODIMP get_accChildCount(LONG* child_count); + virtual STDMETHODIMP get_accChildCount(LONG* child_count); // Retrieves a string that describes the object's default action. STDMETHODIMP get_accDefaultAction(VARIANT var_id, BSTR* default_action); @@ -349,9 +349,12 @@ NativeViewAccessibilityWin // to MSAA states set. static int32 MSAAState(ui::AccessibilityTypes::State state); - private: + protected: NativeViewAccessibilityWin(); + const View* view() const { return view_; } + + private: // Determines navigation direction for accNavigate, based on left, up and // previous being mapped all to previous and right, down, next being mapped // to next. Returns true if navigation direction is next, false otherwise. @@ -388,7 +391,10 @@ NativeViewAccessibilityWin LONG start_offset, ui::TextBoundaryDirection direction); - IAccessible* GetAccessibleFromWebView(long child_id); + // Populates the given vector with all widgets that are either a child + // or are owned by this view's widget, and who are not contained in a + // NativeViewHost. + void PopulateChildWidgetVector(std::vector<Widget*>* child_widgets); // Give CComObject access to the class constructor. template <class Base> friend class CComObject; diff --git a/chromium/ui/views/accessibility/native_view_accessibility_win_unittest.cc b/chromium/ui/views/accessibility/native_view_accessibility_win_unittest.cc index 7dcbac22145..5bd5bed7b91 100644 --- a/chromium/ui/views/accessibility/native_view_accessibility_win_unittest.cc +++ b/chromium/ui/views/accessibility/native_view_accessibility_win_unittest.cc @@ -7,6 +7,7 @@ #include "base/win/scoped_bstr.h" #include "base/win/scoped_comptr.h" #include "base/win/scoped_variant.h" +#include "ui/views/accessibility/native_view_accessibility.h" #include "ui/views/controls/textfield/textfield.h" #include "ui/views/test/views_test_base.h" @@ -61,5 +62,63 @@ TEST_F(NativeViewAcccessibilityWinTest, TextfieldAccessibility) { ASSERT_STREQ(L"New value", textfield->text().c_str()); } +TEST_F(NativeViewAcccessibilityWinTest, UnattachedWebView) { + // This is a regression test. Calling get_accChild on the native accessible + // object for a WebView with no attached WebContents was causing an + // infinite loop and crash. This test simulates that with an ordinary + // View that registers itself as a web view with NativeViewAcccessibility. + + Widget widget; + Widget::InitParams init_params = + CreateParams(Widget::InitParams::TYPE_POPUP); + init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + widget.Init(init_params); + + View* content = new View; + widget.SetContentsView(content); + + View* web_view = new View; + content->AddChildView(web_view); + NativeViewAccessibility::RegisterWebView(web_view); + + base::win::ScopedComPtr<IAccessible> web_view_accessible( + web_view->GetNativeViewAccessible()); + base::win::ScopedComPtr<IDispatch> result_dispatch; + base::win::ScopedVariant child_index(-999); + ASSERT_EQ(E_FAIL, web_view_accessible->get_accChild( + child_index, result_dispatch.Receive())); + + NativeViewAccessibility::UnregisterWebView(web_view); +} + +#if defined(USE_AURA) +TEST_F(NativeViewAcccessibilityWinTest, AuraOwnedWidgets) { + Widget widget; + Widget::InitParams init_params = + CreateParams(Widget::InitParams::TYPE_WINDOW); + init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + widget.Init(init_params); + + base::win::ScopedComPtr<IAccessible> root_view_accessible( + widget.GetRootView()->GetNativeViewAccessible()); + + LONG child_count = 0; + ASSERT_EQ(S_OK, root_view_accessible->get_accChildCount(&child_count)); + ASSERT_EQ(1L, child_count); + + Widget owned_widget; + Widget::InitParams owned_init_params = + CreateParams(Widget::InitParams::TYPE_POPUP); + owned_init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + owned_init_params.child = false; + owned_init_params.parent = widget.GetNativeView(); + owned_widget.Init(owned_init_params); + owned_widget.Show(); + + ASSERT_EQ(S_OK, root_view_accessible->get_accChildCount(&child_count)); + ASSERT_EQ(2L, child_count); +} +#endif + } // namespace test } // namespace views diff --git a/chromium/ui/views/animation/bounds_animator.cc b/chromium/ui/views/animation/bounds_animator.cc index c064cc810f6..839294ff74c 100644 --- a/chromium/ui/views/animation/bounds_animator.cc +++ b/chromium/ui/views/animation/bounds_animator.cc @@ -5,18 +5,18 @@ #include "ui/views/animation/bounds_animator.h" #include "base/memory/scoped_ptr.h" -#include "ui/base/animation/animation_container.h" -#include "ui/base/animation/slide_animation.h" +#include "ui/gfx/animation/animation_container.h" +#include "ui/gfx/animation/slide_animation.h" #include "ui/views/animation/bounds_animator_observer.h" #include "ui/views/view.h" // Duration in milliseconds for animations. static const int kDefaultAnimationDuration = 200; -using ui::Animation; -using ui::AnimationContainer; -using ui::SlideAnimation; -using ui::Tween; +using gfx::Animation; +using gfx::AnimationContainer; +using gfx::SlideAnimation; +using gfx::Tween; namespace views { diff --git a/chromium/ui/views/animation/bounds_animator.h b/chromium/ui/views/animation/bounds_animator.h index 4082b5c38d0..1688dd56235 100644 --- a/chromium/ui/views/animation/bounds_animator.h +++ b/chromium/ui/views/animation/bounds_animator.h @@ -10,13 +10,13 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" #include "base/observer_list.h" -#include "ui/base/animation/animation_container_observer.h" -#include "ui/base/animation/animation_delegate.h" -#include "ui/base/animation/tween.h" +#include "ui/gfx/animation/animation_container_observer.h" +#include "ui/gfx/animation/animation_delegate.h" +#include "ui/gfx/animation/tween.h" #include "ui/gfx/rect.h" #include "ui/views/views_export.h" -namespace ui { +namespace gfx { class SlideAnimation; } @@ -35,12 +35,12 @@ class View; // You can attach an AnimationDelegate to the individual animation for a view // by way of SetAnimationDelegate. Additionally you can attach an observer to // the BoundsAnimator that is notified when all animations are complete. -class VIEWS_EXPORT BoundsAnimator : public ui::AnimationDelegate, - public ui::AnimationContainerObserver { +class VIEWS_EXPORT BoundsAnimator : public gfx::AnimationDelegate, + public gfx::AnimationContainerObserver { public: // If |delete_when_done| is set to true in |SetAnimationDelegate| the // |AnimationDelegate| must subclass this class. - class OwnedAnimationDelegate : public ui::AnimationDelegate { + class OwnedAnimationDelegate : public gfx::AnimationDelegate { public: virtual ~OwnedAnimationDelegate() {} }; @@ -65,11 +65,11 @@ class VIEWS_EXPORT BoundsAnimator : public ui::AnimationDelegate, // Sets the animation for the specified view. BoundsAnimator takes ownership // of the specified animation. - void SetAnimationForView(View* view, ui::SlideAnimation* animation); + void SetAnimationForView(View* view, gfx::SlideAnimation* animation); // Returns the animation for the specified view. BoundsAnimator owns the // returned Animation. - const ui::SlideAnimation* GetAnimationForView(View* view); + const gfx::SlideAnimation* GetAnimationForView(View* view); // Stops animating the specified view. void StopAnimatingView(View* view); @@ -78,7 +78,7 @@ class VIEWS_EXPORT BoundsAnimator : public ui::AnimationDelegate, // |delete_when_done| is true the |delegate| is deleted when done and // |delegate| must subclass OwnedAnimationDelegate. void SetAnimationDelegate(View* view, - ui::AnimationDelegate* delegate, + gfx::AnimationDelegate* delegate, bool delete_when_done); // Returns true if BoundsAnimator is animating the bounds of |view|. @@ -96,14 +96,14 @@ class VIEWS_EXPORT BoundsAnimator : public ui::AnimationDelegate, void SetAnimationDuration(int duration_ms); // Sets the tween type for new animations. Default is EASE_OUT. - void set_tween_type(ui::Tween::Type type) { tween_type_ = type; } + void set_tween_type(gfx::Tween::Type type) { tween_type_ = type; } void AddObserver(BoundsAnimatorObserver* observer); void RemoveObserver(BoundsAnimatorObserver* observer); protected: // Creates the animation to use for animating views. - virtual ui::SlideAnimation* CreateAnimation(); + virtual gfx::SlideAnimation* CreateAnimation(); private: // Tracks data about the view being animated. @@ -123,10 +123,10 @@ class VIEWS_EXPORT BoundsAnimator : public ui::AnimationDelegate, gfx::Rect target_bounds; // The animation. We own this. - ui::SlideAnimation* animation; + gfx::SlideAnimation* animation; // Additional delegate for the animation, may be null. - ui::AnimationDelegate* delegate; + gfx::AnimationDelegate* delegate; }; // Used by AnimationEndedOrCanceled. @@ -137,7 +137,7 @@ class VIEWS_EXPORT BoundsAnimator : public ui::AnimationDelegate, typedef std::map<View*, Data> ViewToDataMap; - typedef std::map<const ui::Animation*, View*> AnimationToViewMap; + typedef std::map<const gfx::Animation*, View*> AnimationToViewMap; // Removes references to |view| and its animation. This does NOT delete the // animation or delegate. @@ -150,22 +150,22 @@ class VIEWS_EXPORT BoundsAnimator : public ui::AnimationDelegate, // Used when changing the animation for a view. This resets the maps for // the animation used by view and returns the current animation. Ownership // of the returned animation passes to the caller. - ui::Animation* ResetAnimationForView(View* view); + gfx::Animation* ResetAnimationForView(View* view); // Invoked from AnimationEnded and AnimationCanceled. - void AnimationEndedOrCanceled(const ui::Animation* animation, + void AnimationEndedOrCanceled(const gfx::Animation* animation, AnimationEndType type); - // ui::AnimationDelegate overrides. - virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; - virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE; - virtual void AnimationCanceled(const ui::Animation* animation) OVERRIDE; + // gfx::AnimationDelegate overrides. + virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; + virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE; + virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE; - // ui::AnimationContainerObserver overrides. + // gfx::AnimationContainerObserver overrides. virtual void AnimationContainerProgressed( - ui::AnimationContainer* container) OVERRIDE; + gfx::AnimationContainer* container) OVERRIDE; virtual void AnimationContainerEmpty( - ui::AnimationContainer* container) OVERRIDE; + gfx::AnimationContainer* container) OVERRIDE; // Parent of all views being animated. View* parent_; @@ -173,7 +173,7 @@ class VIEWS_EXPORT BoundsAnimator : public ui::AnimationDelegate, ObserverList<BoundsAnimatorObserver> observers_; // All animations we create up with the same container. - scoped_refptr<ui::AnimationContainer> container_; + scoped_refptr<gfx::AnimationContainer> container_; // Maps from view being animated to info about the view. ViewToDataMap data_; @@ -189,7 +189,7 @@ class VIEWS_EXPORT BoundsAnimator : public ui::AnimationDelegate, int animation_duration_ms_; - ui::Tween::Type tween_type_; + gfx::Tween::Type tween_type_; DISALLOW_COPY_AND_ASSIGN(BoundsAnimator); }; diff --git a/chromium/ui/views/animation/bounds_animator_unittest.cc b/chromium/ui/views/animation/bounds_animator_unittest.cc index ed7dca590bf..0928fe665b0 100644 --- a/chromium/ui/views/animation/bounds_animator_unittest.cc +++ b/chromium/ui/views/animation/bounds_animator_unittest.cc @@ -5,13 +5,13 @@ #include "ui/views/animation/bounds_animator.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/animation/slide_animation.h" -#include "ui/base/animation/test_animation_delegate.h" +#include "ui/gfx/animation/slide_animation.h" +#include "ui/gfx/animation/test_animation_delegate.h" #include "ui/views/view.h" -using ui::Animation; -using ui::SlideAnimation; -using ui::TestAnimationDelegate; +using gfx::Animation; +using gfx::SlideAnimation; +using gfx::TestAnimationDelegate; namespace views { namespace { @@ -52,7 +52,7 @@ class OwnedDelegate : public BoundsAnimator::OwnedAnimationDelegate { return value; } - // Overridden from ui::AnimationDelegate: + // Overridden from gfx::AnimationDelegate: virtual void AnimationCanceled(const Animation* animation) OVERRIDE { canceled_ = true; } diff --git a/chromium/ui/views/animation/scroll_animator.cc b/chromium/ui/views/animation/scroll_animator.cc index 1e484a37c80..7d689993f2b 100644 --- a/chromium/ui/views/animation/scroll_animator.cc +++ b/chromium/ui/views/animation/scroll_animator.cc @@ -8,7 +8,7 @@ #include <cmath> #include "base/logging.h" -#include "ui/base/animation/slide_animation.h" +#include "ui/gfx/animation/slide_animation.h" namespace { const float kDefaultAcceleration = -1500.0f; // in pixels per second^2 @@ -51,7 +51,7 @@ void ScrollAnimator::Start(float velocity_x, float velocity_y) { velocity_x_ = velocity_x; velocity_y_ = velocity_y; duration_ = -v / acceleration_; // in seconds - animation_.reset(new ui::SlideAnimation(this)); + animation_.reset(new gfx::SlideAnimation(this)); animation_->SetSlideDuration(static_cast<int>(duration_ * 1000)); animation_->Show(); } @@ -61,11 +61,11 @@ void ScrollAnimator::Stop() { animation_.reset(); } -void ScrollAnimator::AnimationEnded(const ui::Animation* animation) { +void ScrollAnimator::AnimationEnded(const gfx::Animation* animation) { Stop(); } -void ScrollAnimator::AnimationProgressed(const ui::Animation* animation) { +void ScrollAnimator::AnimationProgressed(const gfx::Animation* animation) { float t = static_cast<float>(animation->GetCurrentValue()) * duration_; float a_x = velocity_x_ > 0 ? acceleration_ : -acceleration_; float a_y = velocity_y_ > 0 ? acceleration_ : -acceleration_; @@ -75,7 +75,7 @@ void ScrollAnimator::AnimationProgressed(const ui::Animation* animation) { delegate_->OnScroll(dx, dy); } -void ScrollAnimator::AnimationCanceled(const ui::Animation* animation) { +void ScrollAnimator::AnimationCanceled(const gfx::Animation* animation) { Stop(); } diff --git a/chromium/ui/views/animation/scroll_animator.h b/chromium/ui/views/animation/scroll_animator.h index 35e159bc552..525a99801f5 100644 --- a/chromium/ui/views/animation/scroll_animator.h +++ b/chromium/ui/views/animation/scroll_animator.h @@ -7,10 +7,10 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" -#include "ui/base/animation/animation_delegate.h" +#include "ui/gfx/animation/animation_delegate.h" #include "ui/views/views_export.h" -namespace ui { +namespace gfx { class SlideAnimation; } @@ -25,7 +25,7 @@ class VIEWS_EXPORT ScrollDelegate { ~ScrollDelegate() {} }; -class VIEWS_EXPORT ScrollAnimator : public ui::AnimationDelegate { +class VIEWS_EXPORT ScrollAnimator : public gfx::AnimationDelegate { public: // The ScrollAnimator does not own the delegate. Uses default acceleration. explicit ScrollAnimator(ScrollDelegate* delegate); @@ -40,10 +40,10 @@ class VIEWS_EXPORT ScrollAnimator : public ui::AnimationDelegate { bool is_scrolling() const { return !!animation_.get(); } private: - // Implementation of ui::AnimationDelegate. - virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE; - virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; - virtual void AnimationCanceled(const ui::Animation* animation) OVERRIDE; + // Implementation of gfx::AnimationDelegate. + virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE; + virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; + virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE; ScrollDelegate* delegate_; @@ -53,7 +53,7 @@ class VIEWS_EXPORT ScrollAnimator : public ui::AnimationDelegate { float duration_; float acceleration_; - scoped_ptr<ui::SlideAnimation> animation_; + scoped_ptr<gfx::SlideAnimation> animation_; DISALLOW_COPY_AND_ASSIGN(ScrollAnimator); }; diff --git a/chromium/ui/views/bubble/bubble_border.cc b/chromium/ui/views/bubble/bubble_border.cc index 3c9a3206df2..6494c7b2f40 100644 --- a/chromium/ui/views/bubble/bubble_border.cc +++ b/chromium/ui/views/bubble/bubble_border.cc @@ -73,25 +73,53 @@ namespace { // The border and arrow stroke size used in image assets, in pixels. const int kStroke = 1; -// Macros to define arrays of IDR constants used with CreateImageGridPainter. -#define IMAGE_BORDER(x) { x ## _TOP_LEFT, x ## _TOP, x ## _TOP_RIGHT, \ - x ## _LEFT, 0, x ## _RIGHT, \ - x ## _BOTTOM_LEFT, x ## _BOTTOM, x ## _BOTTOM_RIGHT, } -#define IMAGE_BORDER_ACRONYM(x) { x ## _TL, x ## _T, x ## _TR, \ - x ## _L, 0, x ## _R, \ - x ## _BL, x ## _B, x ## _BR, } -#define ARROWS(x) { x ## _LEFT, x ## _TOP, x ## _RIGHT, x ## _BOTTOM, } - -// Bubble border and arrow image resource ids. -const int kShadowImages[] = IMAGE_BORDER_ACRONYM(IDR_BUBBLE_SHADOW); +// Bubble border and arrow image resource ids. They don't use the IMAGE_GRID +// macro because there is no center image. +const int kShadowImages[] = { + IDR_BUBBLE_SHADOW_TL, IDR_BUBBLE_SHADOW_T, IDR_BUBBLE_SHADOW_TR, + IDR_BUBBLE_SHADOW_L, 0, IDR_BUBBLE_SHADOW_R, + IDR_BUBBLE_SHADOW_BL, IDR_BUBBLE_SHADOW_B, IDR_BUBBLE_SHADOW_BR }; const int kShadowArrows[] = { 0, 0, 0, 0 }; -const int kNoShadowImages[] = IMAGE_BORDER_ACRONYM(IDR_BUBBLE); -const int kNoShadowArrows[] = { IDR_BUBBLE_L_ARROW, IDR_BUBBLE_T_ARROW, - IDR_BUBBLE_R_ARROW, IDR_BUBBLE_B_ARROW, }; -const int kBigShadowImages[] = IMAGE_BORDER(IDR_WINDOW_BUBBLE_SHADOW_BIG); -const int kBigShadowArrows[] = ARROWS(IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG); -const int kSmallShadowImages[] = IMAGE_BORDER(IDR_WINDOW_BUBBLE_SHADOW_SMALL); -const int kSmallShadowArrows[] = ARROWS(IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL); + +const int kNoShadowImages[] = { + IDR_BUBBLE_TL, IDR_BUBBLE_T, IDR_BUBBLE_TR, + IDR_BUBBLE_L, 0, IDR_BUBBLE_R, + IDR_BUBBLE_BL, IDR_BUBBLE_B, IDR_BUBBLE_BR }; +const int kNoShadowArrows[] = { + IDR_BUBBLE_L_ARROW, IDR_BUBBLE_T_ARROW, + IDR_BUBBLE_R_ARROW, IDR_BUBBLE_B_ARROW, }; + +const int kBigShadowImages[] = { + IDR_WINDOW_BUBBLE_SHADOW_BIG_TOP_LEFT, + IDR_WINDOW_BUBBLE_SHADOW_BIG_TOP, + IDR_WINDOW_BUBBLE_SHADOW_BIG_TOP_RIGHT, + IDR_WINDOW_BUBBLE_SHADOW_BIG_LEFT, + 0, + IDR_WINDOW_BUBBLE_SHADOW_BIG_RIGHT, + IDR_WINDOW_BUBBLE_SHADOW_BIG_BOTTOM_LEFT, + IDR_WINDOW_BUBBLE_SHADOW_BIG_BOTTOM, + IDR_WINDOW_BUBBLE_SHADOW_BIG_BOTTOM_RIGHT }; +const int kBigShadowArrows[] = { + IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG_LEFT, + IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG_TOP, + IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG_RIGHT, + IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG_BOTTOM }; + +const int kSmallShadowImages[] = { + IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP_LEFT, + IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP, + IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP_RIGHT, + IDR_WINDOW_BUBBLE_SHADOW_SMALL_LEFT, + 0, + IDR_WINDOW_BUBBLE_SHADOW_SMALL_RIGHT, + IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM_LEFT, + IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM, + IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM_RIGHT }; +const int kSmallShadowArrows[] = { + IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL_LEFT, + IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL_TOP, + IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL_RIGHT, + IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL_BOTTOM }; using internal::BorderImages; diff --git a/chromium/ui/views/bubble/bubble_delegate.cc b/chromium/ui/views/bubble/bubble_delegate.cc index 3987589f3fc..af08994d487 100644 --- a/chromium/ui/views/bubble/bubble_delegate.cc +++ b/chromium/ui/views/bubble/bubble_delegate.cc @@ -4,7 +4,7 @@ #include "ui/views/bubble/bubble_delegate.h" -#include "ui/base/animation/slide_animation.h" +#include "ui/gfx/animation/slide_animation.h" #include "ui/gfx/color_utils.h" #include "ui/gfx/rect.h" #include "ui/native_theme/native_theme.h" @@ -46,6 +46,8 @@ Widget* CreateBubbleWidget(BubbleDelegateView* bubble) { return bubble_widget; } +} // namespace + #if defined(OS_WIN) && !defined(USE_AURA) // Windows uses two widgets and some extra complexity to host partially // transparent native controls and use per-pixel HWND alpha on the border. @@ -60,8 +62,7 @@ class BubbleBorderDelegate : public WidgetDelegate, } virtual ~BubbleBorderDelegate() { - if (bubble_ && bubble_->GetWidget()) - bubble_->GetWidget()->RemoveObserver(this); + DetachFromBubble(); } // WidgetDelegate overrides: @@ -82,17 +83,30 @@ class BubbleBorderDelegate : public WidgetDelegate, // WidgetObserver overrides: virtual void OnWidgetDestroying(Widget* widget) OVERRIDE { - bubble_ = NULL; + DetachFromBubble(); widget_->Close(); } private: + // Removes state installed on |bubble_|, including references |bubble_| has to + // us. + void DetachFromBubble() { + if (!bubble_) + return; + if (bubble_->GetWidget()) + bubble_->GetWidget()->RemoveObserver(this); + bubble_->border_widget_ = NULL; + bubble_ = NULL; + } + BubbleDelegateView* bubble_; Widget* widget_; DISALLOW_COPY_AND_ASSIGN(BubbleBorderDelegate); }; +namespace { + // Create a widget to host the bubble's border. Widget* CreateBorderWidget(BubbleDelegateView* bubble) { Widget* border_widget = new Widget(); @@ -106,10 +120,11 @@ Widget* CreateBorderWidget(BubbleDelegateView* bubble) { border_widget->set_focus_on_creation(false); return border_widget; } -#endif } // namespace +#endif + BubbleDelegateView::BubbleDelegateView() : close_on_esc_(true), close_on_deactivate_(true), @@ -223,20 +238,21 @@ void BubbleDelegateView::OnWidgetDestroying(Widget* widget) { } } +void BubbleDelegateView::OnWidgetVisibilityChanging(Widget* widget, + bool visible) { +#if defined(OS_WIN) + // On Windows we need to handle this before the bubble is visible or hidden. + // Please see the comment on the OnWidgetVisibilityChanging function. On + // other platforms it is fine to handle it after the bubble is shown/hidden. + HandleVisibilityChanged(widget, visible); +#endif +} + void BubbleDelegateView::OnWidgetVisibilityChanged(Widget* widget, bool visible) { - if (widget != GetWidget()) - return; - - if (visible) { - if (border_widget_) - border_widget_->ShowInactive(); - if (anchor_widget() && anchor_widget()->GetTopLevelWidget()) - anchor_widget()->GetTopLevelWidget()->DisableInactiveRendering(); - } else { - if (border_widget_) - border_widget_->Hide(); - } +#if !defined(OS_WIN) + HandleVisibilityChanged(widget, visible); +#endif } void BubbleDelegateView::OnWidgetActivationChanged(Widget* widget, @@ -269,7 +285,7 @@ void BubbleDelegateView::StartFade(bool fade_in) { else GetWidget()->Close(); #else - fade_animation_.reset(new ui::SlideAnimation(this)); + fade_animation_.reset(new gfx::SlideAnimation(this)); fade_animation_->SetSlideDuration(GetFadeDuration()); fade_animation_->Reset(fade_in ? 0.0 : 1.0); if (fade_in) { @@ -322,7 +338,7 @@ void BubbleDelegateView::OnNativeThemeChanged(const ui::NativeTheme* theme) { UpdateColorsFromTheme(theme); } -void BubbleDelegateView::AnimationEnded(const ui::Animation* animation) { +void BubbleDelegateView::AnimationEnded(const gfx::Animation* animation) { if (animation != fade_animation_.get()) return; bool closed = fade_animation_->GetCurrentValue() == 0; @@ -331,7 +347,7 @@ void BubbleDelegateView::AnimationEnded(const ui::Animation* animation) { GetWidget()->Close(); } -void BubbleDelegateView::AnimationProgressed(const ui::Animation* animation) { +void BubbleDelegateView::AnimationProgressed(const gfx::Animation* animation) { if (animation != fade_animation_.get()) return; DCHECK(fade_animation_->is_animating()); @@ -405,4 +421,20 @@ gfx::Rect BubbleDelegateView::GetBubbleClientBounds() const { } #endif +void BubbleDelegateView::HandleVisibilityChanged(Widget* widget, + bool visible) { + if (widget != GetWidget()) + return; + + if (visible) { + if (border_widget_) + border_widget_->ShowInactive(); + if (anchor_widget() && anchor_widget()->GetTopLevelWidget()) + anchor_widget()->GetTopLevelWidget()->DisableInactiveRendering(); + } else { + if (border_widget_) + border_widget_->Hide(); + } +} + } // namespace views diff --git a/chromium/ui/views/bubble/bubble_delegate.h b/chromium/ui/views/bubble/bubble_delegate.h index c534273dd6f..4a0bb30ec01 100644 --- a/chromium/ui/views/bubble/bubble_delegate.h +++ b/chromium/ui/views/bubble/bubble_delegate.h @@ -6,21 +6,19 @@ #define UI_VIEWS_BUBBLE_BUBBLE_DELEGATE_H_ #include "base/gtest_prod_util.h" -#include "ui/base/animation/animation_delegate.h" +#include "ui/gfx/animation/animation_delegate.h" #include "ui/views/bubble/bubble_border.h" #include "ui/views/widget/widget_delegate.h" #include "ui/views/widget/widget_observer.h" namespace gfx { class Rect; -} - -namespace ui { class SlideAnimation; } namespace views { +class BubbleBorderDelegate; class BubbleFrameView; // BubbleDelegateView creates frame and client views for bubble Widgets. @@ -28,7 +26,7 @@ class BubbleFrameView; // /////////////////////////////////////////////////////////////////////////////// class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView, - public ui::AnimationDelegate, + public gfx::AnimationDelegate, public WidgetObserver { public: BubbleDelegateView(); @@ -47,7 +45,10 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView, // WidgetObserver overrides: virtual void OnWidgetDestroying(Widget* widget) OVERRIDE; - virtual void OnWidgetVisibilityChanged(Widget* widget, bool visible) OVERRIDE; + virtual void OnWidgetVisibilityChanging(Widget* widget, bool visible) + OVERRIDE; + virtual void OnWidgetVisibilityChanged(Widget* widget, bool visible) + OVERRIDE; virtual void OnWidgetActivationChanged(Widget* widget, bool active) OVERRIDE; virtual void OnWidgetBoundsChanged(Widget* widget, const gfx::Rect& new_bounds) OVERRIDE; @@ -133,9 +134,9 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView, virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE; virtual void OnNativeThemeChanged(const ui::NativeTheme* theme) OVERRIDE; - // ui::AnimationDelegate overrides: - virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE; - virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; + // gfx::AnimationDelegate overrides: + virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE; + virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; // Perform view initialization on the contents for bubble sizing. virtual void Init(); @@ -150,6 +151,8 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView, BubbleFrameView* GetBubbleFrameView() const; private: + friend class BubbleBorderDelegate; + FRIEND_TEST_ALL_PREFIXES(BubbleDelegateTest, CreateDelegate); FRIEND_TEST_ALL_PREFIXES(BubbleDelegateTest, NonClientHitTest); @@ -161,8 +164,11 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView, gfx::Rect GetBubbleClientBounds() const; #endif + // Handles widget visibility changes. + void HandleVisibilityChanged(Widget* widget, bool visible); + // Fade animation for bubble. - scoped_ptr<ui::SlideAnimation> fade_animation_; + scoped_ptr<gfx::SlideAnimation> fade_animation_; // Flags controlling bubble closure on the escape key and deactivation. bool close_on_esc_; diff --git a/chromium/ui/views/bubble/bubble_frame_view.cc b/chromium/ui/views/bubble/bubble_frame_view.cc index 2bd579d79d9..dca1bc4b85b 100644 --- a/chromium/ui/views/bubble/bubble_frame_view.cc +++ b/chromium/ui/views/bubble/bubble_frame_view.cc @@ -168,18 +168,11 @@ gfx::Insets BubbleFrameView::GetInsets() const { } gfx::Size BubbleFrameView::GetPreferredSize() { - const gfx::Size client(GetWidget()->client_view()->GetPreferredSize()); - gfx::Size size(GetUpdatedWindowBounds(gfx::Rect(), client, false).size()); - // Accommodate the width of the title bar elements. - int title_bar_width = GetInsets().width() + border()->GetInsets().width(); - if (!title_->text().empty()) - title_bar_width += kTitleLeftInset + title_->GetPreferredSize().width(); - if (close_->visible()) - title_bar_width += close_->width() + 1; - if (titlebar_extra_view_ != NULL) - title_bar_width += titlebar_extra_view_->GetPreferredSize().width(); - size.SetToMax(gfx::Size(title_bar_width, 0)); - return size; + return GetSizeForClientSize(GetWidget()->client_view()->GetPreferredSize()); +} + +gfx::Size BubbleFrameView::GetMinimumSize() { + return GetSizeForClientSize(GetWidget()->client_view()->GetMinimumSize()); } void BubbleFrameView::Layout() { @@ -334,4 +327,19 @@ void BubbleFrameView::OffsetArrowIfOffScreen(const gfx::Rect& anchor_rect, SchedulePaint(); } +gfx::Size BubbleFrameView::GetSizeForClientSize(const gfx::Size& client_size) { + gfx::Size size( + GetUpdatedWindowBounds(gfx::Rect(), client_size, false).size()); + // Accommodate the width of the title bar elements. + int title_bar_width = GetInsets().width() + border()->GetInsets().width(); + if (!title_->text().empty()) + title_bar_width += kTitleLeftInset + title_->GetPreferredSize().width(); + if (close_->visible()) + title_bar_width += close_->width() + 1; + if (titlebar_extra_view_ != NULL) + title_bar_width += titlebar_extra_view_->GetPreferredSize().width(); + size.SetToMax(gfx::Size(title_bar_width, 0)); + return size; +} + } // namespace views diff --git a/chromium/ui/views/bubble/bubble_frame_view.h b/chromium/ui/views/bubble/bubble_frame_view.h index 7dc459623ba..48ef52dd347 100644 --- a/chromium/ui/views/bubble/bubble_frame_view.h +++ b/chromium/ui/views/bubble/bubble_frame_view.h @@ -46,6 +46,7 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView, // View overrides: virtual gfx::Insets GetInsets() const OVERRIDE; virtual gfx::Size GetPreferredSize() OVERRIDE; + virtual gfx::Size GetMinimumSize() OVERRIDE; virtual void Layout() OVERRIDE; virtual const char* GetClassName() const OVERRIDE; virtual void ChildPreferredSizeChanged(View* child) OVERRIDE; @@ -87,6 +88,9 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView, void OffsetArrowIfOffScreen(const gfx::Rect& anchor_rect, const gfx::Size& client_size); + // Calculates the size needed to accommodate the given client area. + gfx::Size GetSizeForClientSize(const gfx::Size& client_size); + // The bubble border. BubbleBorder* bubble_border_; diff --git a/chromium/ui/views/bubble/tray_bubble_view.cc b/chromium/ui/views/bubble/tray_bubble_view.cc index 0d8accdbdb5..6192e51c432 100644 --- a/chromium/ui/views/bubble/tray_bubble_view.cc +++ b/chromium/ui/views/bubble/tray_bubble_view.cc @@ -12,10 +12,10 @@ #include "third_party/skia/include/core/SkPath.h" #include "third_party/skia/include/effects/SkBlurImageFilter.h" #include "ui/base/accessibility/accessible_view_state.h" -#include "ui/base/events/event.h" #include "ui/base/l10n/l10n_util.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_delegate.h" +#include "ui/events/event.h" #include "ui/gfx/canvas.h" #include "ui/gfx/insets.h" #include "ui/gfx/path.h" @@ -38,12 +38,40 @@ const int kArrowOffsetLeft = 9; const int kArrowOffsetRight = -5; const int kOffsetLeftRightForTopBottomOrientation = 5; +// The sampling time for mouse position changes in ms - which is roughly a frame +// time. +const int kFrameTimeInMS = 30; } // namespace namespace views { namespace internal { +// Detects any mouse movement. This is needed to detect mouse movements by the +// user over the bubble if the bubble got created underneath the cursor. +class MouseMoveDetectorHost : public MouseWatcherHost { + public: + MouseMoveDetectorHost(); + virtual ~MouseMoveDetectorHost(); + + virtual bool Contains(const gfx::Point& screen_point, + MouseEventType type) OVERRIDE; + private: + + DISALLOW_COPY_AND_ASSIGN(MouseMoveDetectorHost); +}; + +MouseMoveDetectorHost::MouseMoveDetectorHost() { +} + +MouseMoveDetectorHost::~MouseMoveDetectorHost() { +} + +bool MouseMoveDetectorHost::Contains(const gfx::Point& screen_point, + MouseEventType type) { + return false; +} + // Custom border for TrayBubbleView. Contains special logic for GetBounds() // to stack bubbles with no arrows correctly. Also calculates the arrow offset. class TrayBubbleBorder : public BubbleBorder { @@ -293,7 +321,8 @@ TrayBubbleView::TrayBubbleView(gfx::NativeView parent_window, delegate_(delegate), preferred_width_(init_params.min_width), bubble_border_(NULL), - is_gesture_dragging_(false) { + is_gesture_dragging_(false), + mouse_actively_entered_(false) { set_parent_window(parent_window); set_notify_enter_exit_on_child(true); set_close_on_deactivate(init_params.close_on_deactivate); @@ -309,6 +338,7 @@ TrayBubbleView::TrayBubbleView(gfx::NativeView parent_window, } TrayBubbleView::~TrayBubbleView() { + mouse_watcher_.reset(); // Inform host items (models) that their views are being destroyed. if (delegate_) delegate_->BubbleViewDestroyed(); @@ -414,12 +444,36 @@ int TrayBubbleView::GetHeightForWidth(int width) { } void TrayBubbleView::OnMouseEntered(const ui::MouseEvent& event) { - if (delegate_) + mouse_watcher_.reset(); + if (delegate_ && !(event.flags() & ui::EF_IS_SYNTHESIZED)) { + // Coming here the user was actively moving the mouse over the bubble and + // we inform the delegate that we entered. This will prevent the bubble + // to auto close. delegate_->OnMouseEnteredView(); + mouse_actively_entered_ = true; + } else { + // Coming here the bubble got shown and the mouse was 'accidentally' over it + // which is not a reason to prevent the bubble to auto close. As such we + // do not call the delegate, but wait for the first mouse move within the + // bubble. The used MouseWatcher will notify use of a movement and call + // |MouseMovedOutOfHost|. + mouse_watcher_.reset(new MouseWatcher( + new views::internal::MouseMoveDetectorHost(), + this)); + // Set the mouse sampling frequency to roughly a frame time so that the user + // cannot see a lag. + mouse_watcher_->set_notify_on_exit_time( + base::TimeDelta::FromMilliseconds(kFrameTimeInMS)); + mouse_watcher_->Start(); + } } void TrayBubbleView::OnMouseExited(const ui::MouseEvent& event) { - if (delegate_) + // If there was a mouse watcher waiting for mouse movements we disable it + // immediately since we now leave the bubble. + mouse_watcher_.reset(); + // Do not notify the delegate of an exit if we never told it that we entered. + if (delegate_ && mouse_actively_entered_) delegate_->OnMouseExitedView(); } @@ -430,6 +484,15 @@ void TrayBubbleView::GetAccessibleState(ui::AccessibleViewState* state) { } } +void TrayBubbleView::MouseMovedOutOfHost() { + // The mouse was accidentally over the bubble when it opened and the AutoClose + // logic was not activated. Now that the user did move the mouse we tell the + // delegate to disable AutoClose. + delegate_->OnMouseEnteredView(); + mouse_actively_entered_ = true; + mouse_watcher_->Stop(); +} + void TrayBubbleView::ChildPreferredSizeChanged(View* child) { SizeToContents(); } diff --git a/chromium/ui/views/bubble/tray_bubble_view.h b/chromium/ui/views/bubble/tray_bubble_view.h index 9c96c5456b5..1e9d48298ea 100644 --- a/chromium/ui/views/bubble/tray_bubble_view.h +++ b/chromium/ui/views/bubble/tray_bubble_view.h @@ -7,6 +7,7 @@ #include "base/memory/scoped_ptr.h" #include "ui/views/bubble/bubble_delegate.h" +#include "ui/views/mouse_watcher.h" #include "ui/views/views_export.h" // Specialized bubble view for bubbles associated with a tray icon (e.g. the @@ -30,7 +31,8 @@ class TrayBubbleBorder; class TrayBubbleContentMask; } -class VIEWS_EXPORT TrayBubbleView : public views::BubbleDelegateView { +class VIEWS_EXPORT TrayBubbleView : public views::BubbleDelegateView, + public views::MouseWatcherListener { public: // AnchorType differentiates between bubbles that are anchored on a tray // element (ANCHOR_TYPE_TRAY) and display an arrow, or that are floating on @@ -62,6 +64,8 @@ class VIEWS_EXPORT TrayBubbleView : public views::BubbleDelegateView { virtual void BubbleViewDestroyed() = 0; // Called when the mouse enters/exits the view. + // Note: This event will only be called if the mouse gets actively moved by + // the user to enter the view. virtual void OnMouseEnteredView() = 0; virtual void OnMouseExitedView() = 0; @@ -159,6 +163,9 @@ class VIEWS_EXPORT TrayBubbleView : public views::BubbleDelegateView { virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE; virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; + // Overridden from MouseWatcherListener + virtual void MouseMovedOutOfHost() OVERRIDE; + protected: TrayBubbleView(gfx::NativeView parent_window, views::View* anchor, @@ -181,6 +188,13 @@ class VIEWS_EXPORT TrayBubbleView : public views::BubbleDelegateView { scoped_ptr<internal::TrayBubbleContentMask> bubble_content_mask_; bool is_gesture_dragging_; + // True once the mouse cursor was actively moved by the user over the bubble. + // Only then the OnMouseExitedView() event will get passed on to listeners. + bool mouse_actively_entered_; + + // Used to find any mouse movements. + scoped_ptr<MouseWatcher> mouse_watcher_; + DISALLOW_COPY_AND_ASSIGN(TrayBubbleView); }; diff --git a/chromium/ui/views/color_chooser/color_chooser_view.cc b/chromium/ui/views/color_chooser/color_chooser_view.cc index 07a33a984a4..c4a136b6ea4 100644 --- a/chromium/ui/views/color_chooser/color_chooser_view.cc +++ b/chromium/ui/views/color_chooser/color_chooser_view.cc @@ -8,8 +8,8 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" -#include "ui/base/events/event.h" -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/canvas.h" #include "ui/views/background.h" #include "ui/views/border.h" diff --git a/chromium/ui/views/controls/button/blue_button.cc b/chromium/ui/views/controls/button/blue_button.cc index a17441e1cbe..3e52afd896e 100644 --- a/chromium/ui/views/controls/button/blue_button.cc +++ b/chromium/ui/views/controls/button/blue_button.cc @@ -63,7 +63,12 @@ BlueButton::BlueButton(ButtonListener* listener, const string16& text) button_border->SetPainter(true, STATE_DISABLED, Painter::CreateImagePainter( *rb.GetImageSkiaNamed(IDR_BLUE_BUTTON_DISABLED), insets)); +} + +BlueButton::~BlueButton() {} +void BlueButton::ResetColorsFromNativeTheme() { + LabelButton::ResetColorsFromNativeTheme(); if (!gfx::IsInvertedColorScheme()) { for (size_t state = STATE_NORMAL; state < STATE_COUNT; ++state) SetTextColor(static_cast<ButtonState>(state), kBlueButtonTextColor); @@ -72,15 +77,8 @@ BlueButton::BlueButton(ButtonListener* listener, const string16& text) } } -BlueButton::~BlueButton() {} - const char* BlueButton::GetClassName() const { return BlueButton::kViewClassName; } -// TODO(msw): Re-enable animations for blue buttons. See crbug.com/239121. -const ui::Animation* BlueButton::GetThemeAnimation() const { - return NULL; -} - } // namespace views diff --git a/chromium/ui/views/controls/button/blue_button.h b/chromium/ui/views/controls/button/blue_button.h index 0415bf429c7..a169fba85d1 100644 --- a/chromium/ui/views/controls/button/blue_button.h +++ b/chromium/ui/views/controls/button/blue_button.h @@ -6,7 +6,6 @@ #define UI_VIEWS_CONTROLS_BUTTON_BLUE_BUTTON_H_ #include "base/compiler_specific.h" -#include "base/strings/string16.h" #include "ui/views/controls/button/label_button.h" namespace views { @@ -21,8 +20,8 @@ class VIEWS_EXPORT BlueButton : public LabelButton { private: // Overridden from LabelButton: + virtual void ResetColorsFromNativeTheme() OVERRIDE; virtual const char* GetClassName() const OVERRIDE; - virtual const ui::Animation* GetThemeAnimation() const OVERRIDE; DISALLOW_COPY_AND_ASSIGN(BlueButton); }; diff --git a/chromium/ui/views/controls/button/custom_button.cc b/chromium/ui/views/controls/button/custom_button.cc index f8e8b58d2cf..4a15975d5b8 100644 --- a/chromium/ui/views/controls/button/custom_button.cc +++ b/chromium/ui/views/controls/button/custom_button.cc @@ -5,9 +5,9 @@ #include "ui/views/controls/button/custom_button.h" #include "ui/base/accessibility/accessible_view_state.h" -#include "ui/base/animation/throb_animation.h" -#include "ui/base/events/event.h" -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/keyboard_codes.h" +#include "ui/gfx/animation/throb_animation.h" #include "ui/gfx/screen.h" #include "ui/views/widget/widget.h" @@ -277,9 +277,9 @@ void CustomButton::VisibilityChanged(View* starting_from, bool visible) { } //////////////////////////////////////////////////////////////////////////////// -// CustomButton, ui::AnimationDelegate implementation: +// CustomButton, gfx::AnimationDelegate implementation: -void CustomButton::AnimationProgressed(const ui::Animation* animation) { +void CustomButton::AnimationProgressed(const gfx::Animation* animation) { SchedulePaint(); } @@ -293,7 +293,7 @@ CustomButton::CustomButton(ButtonListener* listener) is_throbbing_(false), triggerable_event_flags_(ui::EF_LEFT_MOUSE_BUTTON), request_focus_on_press_(true) { - hover_animation_.reset(new ui::ThrobAnimation(this)); + hover_animation_.reset(new gfx::ThrobAnimation(this)); hover_animation_->SetSlideDuration(kHoverFadeDurationMs); } diff --git a/chromium/ui/views/controls/button/custom_button.h b/chromium/ui/views/controls/button/custom_button.h index 4d864b42abb..ecb49f60a3f 100644 --- a/chromium/ui/views/controls/button/custom_button.h +++ b/chromium/ui/views/controls/button/custom_button.h @@ -6,11 +6,11 @@ #define UI_VIEWS_CONTROLS_BUTTON_CUSTOM_BUTTON_H_ #include "base/memory/scoped_ptr.h" -#include "ui/base/animation/animation_delegate.h" -#include "ui/base/events/event_constants.h" +#include "ui/events/event_constants.h" +#include "ui/gfx/animation/animation_delegate.h" #include "ui/views/controls/button/button.h" -namespace ui { +namespace gfx { class ThrobAnimation; } @@ -24,7 +24,7 @@ class CustomButtonStateChangedDelegate; // part of the focus chain. Call set_focusable(true) to make it part of the // focus chain. class VIEWS_EXPORT CustomButton : public Button, - public ui::AnimationDelegate { + public gfx::AnimationDelegate { public: // The menu button's class name. static const char kViewClassName[]; @@ -84,8 +84,8 @@ class VIEWS_EXPORT CustomButton : public Button, virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; virtual void VisibilityChanged(View* starting_from, bool is_visible) OVERRIDE; - // Overridden from ui::AnimationDelegate: - virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; + // Overridden from gfx::AnimationDelegate: + virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; // Takes ownership of the delegate. void set_state_changed_delegate(CustomButtonStateChangedDelegate* delegate) { @@ -120,7 +120,7 @@ class VIEWS_EXPORT CustomButton : public Button, ButtonState state_; // Hover animation. - scoped_ptr<ui::ThrobAnimation> hover_animation_; + scoped_ptr<gfx::ThrobAnimation> hover_animation_; private: // Should we animate when the state changes? Defaults to true. diff --git a/chromium/ui/views/controls/button/image_button.cc b/chromium/ui/views/controls/button/image_button.cc index ff355ebd68e..17f74167c7c 100644 --- a/chromium/ui/views/controls/button/image_button.cc +++ b/chromium/ui/views/controls/button/image_button.cc @@ -6,7 +6,7 @@ #include "base/strings/utf_string_conversions.h" #include "ui/base/accessibility/accessible_view_state.h" -#include "ui/base/animation/throb_animation.h" +#include "ui/gfx/animation/throb_animation.h" #include "ui/gfx/canvas.h" #include "ui/gfx/image/image_skia_operations.h" #include "ui/views/widget/widget.h" @@ -16,6 +16,8 @@ namespace views { static const int kDefaultWidth = 16; // Default button width if no theme. static const int kDefaultHeight = 14; // Default button height if no theme. +const char ImageButton::kViewClassName[] = "ImageButton"; + //////////////////////////////////////////////////////////////////////////////// // ImageButton, public: @@ -84,6 +86,10 @@ gfx::Size ImageButton::GetPreferredSize() { return size; } +const char* ImageButton::GetClassName() const { + return kViewClassName; +} + void ImageButton::OnPaint(gfx::Canvas* canvas) { // Call the base class first to paint any background/borders. View::OnPaint(canvas); diff --git a/chromium/ui/views/controls/button/image_button.h b/chromium/ui/views/controls/button/image_button.h index 4015def5a6a..5ea0fa91ead 100644 --- a/chromium/ui/views/controls/button/image_button.h +++ b/chromium/ui/views/controls/button/image_button.h @@ -20,6 +20,8 @@ namespace views { class VIEWS_EXPORT ImageButton : public CustomButton { public: + static const char kViewClassName[]; + enum HorizontalAlignment { ALIGN_LEFT = 0, ALIGN_CENTER, @@ -56,6 +58,7 @@ class VIEWS_EXPORT ImageButton : public CustomButton { // Overridden from View: virtual gfx::Size GetPreferredSize() OVERRIDE; + virtual const char* GetClassName() const OVERRIDE; virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; // Sets preferred size, so it could be correctly positioned in layout even if diff --git a/chromium/ui/views/controls/button/label_button.cc b/chromium/ui/views/controls/button/label_button.cc index 9fab63b0086..ae4ffe05311 100644 --- a/chromium/ui/views/controls/button/label_button.cc +++ b/chromium/ui/views/controls/button/label_button.cc @@ -6,8 +6,8 @@ #include "base/logging.h" #include "grit/ui_resources.h" -#include "ui/base/animation/throb_animation.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/animation/throb_animation.h" #include "ui/gfx/sys_color_change_listener.h" #include "ui/native_theme/native_theme.h" #include "ui/views/controls/button/label_button_border.h" @@ -128,7 +128,7 @@ void LabelButton::SetIsDefault(bool is_default) { // STYLE_BUTTON uses bold text to indicate default buttons. if (style_ == STYLE_BUTTON) { int style = label_->font().GetStyle(); - style = is_default ? style | gfx::Font::BOLD : style & !gfx::Font::BOLD; + style = is_default ? style | gfx::Font::BOLD : style & ~gfx::Font::BOLD; label_->SetFont(label_->font().DeriveFont(0, style)); } } @@ -257,10 +257,6 @@ void LabelButton::GetExtraParams(ui::NativeTheme::ExtraParams* params) const { params->button.background_color = label()->background_color(); } -void LabelButton::UpdateImage() { - image_->SetImage(GetImage(state())); -} - void LabelButton::ResetColorsFromNativeTheme() { const ui::NativeTheme* theme = GetNativeTheme(); SkColor colors[STATE_COUNT] = { @@ -277,9 +273,6 @@ void LabelButton::ResetColorsFromNativeTheme() { theme == ui::NativeThemeWin::instance()); #endif - label_->SetBackgroundColor(theme->GetSystemColor( - ui::NativeTheme::kColorId_ButtonBackgroundColor)); - // Use hardcoded colors for inverted color scheme support and STYLE_BUTTON. if (gfx::IsInvertedColorScheme()) { constant_text_color = true; @@ -290,6 +283,8 @@ void LabelButton::ResetColorsFromNativeTheme() { } else if (style() == STYLE_BUTTON) { constant_text_color = true; colors[STATE_NORMAL] = kStyleButtonTextColor; + label_->SetBackgroundColor(theme->GetSystemColor( + ui::NativeTheme::kColorId_ButtonBackgroundColor)); label_->SetAutoColorReadabilityEnabled(false); label_->SetShadowColors(kStyleButtonShadowColor, kStyleButtonShadowColor); label_->SetShadowOffset(0, 1); @@ -306,6 +301,10 @@ void LabelButton::ResetColorsFromNativeTheme() { } } +void LabelButton::UpdateImage() { + image_->SetImage(GetImage(state())); +} + void LabelButton::StateChanged() { const gfx::Size previous_image_size(image_->GetPreferredSize()); UpdateImage(); @@ -346,7 +345,7 @@ ui::NativeTheme::State LabelButton::GetThemeState( return ui::NativeTheme::kNormal; } -const ui::Animation* LabelButton::GetThemeAnimation() const { +const gfx::Animation* LabelButton::GetThemeAnimation() const { #if defined(OS_WIN) if (style() == STYLE_NATIVE_TEXTBUTTON && GetNativeTheme() == ui::NativeThemeWin::instance()) { diff --git a/chromium/ui/views/controls/button/label_button.h b/chromium/ui/views/controls/button/label_button.h index 0f501914dc3..f48e9a8e2eb 100644 --- a/chromium/ui/views/controls/button/label_button.h +++ b/chromium/ui/views/controls/button/label_button.h @@ -73,6 +73,9 @@ class VIEWS_EXPORT LabelButton : public CustomButton, // Fill |params| with information about the button. virtual void GetExtraParams(ui::NativeTheme::ExtraParams* params) const; + // Resets colors from the NativeTheme, explicitly set colors are unchanged. + virtual void ResetColorsFromNativeTheme(); + // Updates the image view to contain the appropriate button state image. void UpdateImage(); @@ -83,9 +86,6 @@ class VIEWS_EXPORT LabelButton : public CustomButton, FRIEND_TEST_ALL_PREFIXES(LabelButtonTest, LabelAndImage); FRIEND_TEST_ALL_PREFIXES(LabelButtonTest, Font); - // Resets colors from the NativeTheme, explicitly set colors are unchanged. - void ResetColorsFromNativeTheme(); - // Overridden from CustomButton: virtual void StateChanged() OVERRIDE; @@ -98,7 +98,7 @@ class VIEWS_EXPORT LabelButton : public CustomButton, virtual gfx::Rect GetThemePaintRect() const OVERRIDE; virtual ui::NativeTheme::State GetThemeState( ui::NativeTheme::ExtraParams* params) const OVERRIDE; - virtual const ui::Animation* GetThemeAnimation() const OVERRIDE; + virtual const gfx::Animation* GetThemeAnimation() const OVERRIDE; virtual ui::NativeTheme::State GetBackgroundThemeState( ui::NativeTheme::ExtraParams* params) const OVERRIDE; virtual ui::NativeTheme::State GetForegroundThemeState( diff --git a/chromium/ui/views/controls/button/label_button_border.cc b/chromium/ui/views/controls/button/label_button_border.cc index efb80df3a1b..fb6ea0695b8 100644 --- a/chromium/ui/views/controls/button/label_button_border.cc +++ b/chromium/ui/views/controls/button/label_button_border.cc @@ -6,10 +6,13 @@ #include "base/logging.h" #include "grit/ui_resources.h" -#include "ui/base/animation/animation.h" +#include "third_party/skia/include/core/SkPaint.h" +#include "third_party/skia/include/effects/SkLerpXfermode.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/animation/animation.h" #include "ui/gfx/canvas.h" #include "ui/gfx/rect.h" +#include "ui/gfx/skia_util.h" #include "ui/gfx/sys_color_change_listener.h" #include "ui/native_theme/native_theme.h" #include "ui/views/controls/button/label_button.h" @@ -115,21 +118,26 @@ void LabelButtonBorder::Paint(const View& view, gfx::Canvas* canvas) { gfx::Rect rect(native_theme_delegate->GetThemePaintRect()); ui::NativeTheme::ExtraParams extra; const ui::NativeTheme* theme = view.GetNativeTheme(); - const ui::Animation* animation = native_theme_delegate->GetThemeAnimation(); + const gfx::Animation* animation = native_theme_delegate->GetThemeAnimation(); ui::NativeTheme::State state = native_theme_delegate->GetThemeState(&extra); if (animation && animation->is_animating()) { - // Composite the background and foreground painters during state animations. - int alpha = animation->CurrentValueBetween(0, 0xff); + // Linearly interpolate background and foreground painters during animation. + const SkRect sk_rect = gfx::RectToSkRect(rect); + canvas->sk_canvas()->saveLayer(&sk_rect, NULL); state = native_theme_delegate->GetBackgroundThemeState(&extra); - canvas->SaveLayerAlpha(static_cast<uint8>(0xff - alpha)); PaintHelper(this, canvas, theme, part, state, rect, extra); - canvas->Restore(); + SkPaint paint; + skia::RefPtr<SkXfermode> sk_lerp_xfer = + skia::AdoptRef(SkLerpXfermode::Create(animation->GetCurrentValue())); + paint.setXfermode(sk_lerp_xfer.get()); + canvas->sk_canvas()->saveLayer(&sk_rect, &paint); state = native_theme_delegate->GetForegroundThemeState(&extra); - canvas->SaveLayerAlpha(static_cast<uint8>(alpha)); PaintHelper(this, canvas, theme, part, state, rect, extra); - canvas->Restore(); + canvas->sk_canvas()->restore(); + + canvas->sk_canvas()->restore(); } else { PaintHelper(this, canvas, theme, part, state, rect, extra); } diff --git a/chromium/ui/views/controls/button/menu_button.cc b/chromium/ui/views/controls/button/menu_button.cc index 5a20d52b12a..b2e70377281 100644 --- a/chromium/ui/views/controls/button/menu_button.cc +++ b/chromium/ui/views/controls/button/menu_button.cc @@ -9,15 +9,16 @@ #include "grit/ui_strings.h" #include "ui/base/accessibility/accessible_view_state.h" #include "ui/base/dragdrop/drag_drop_types.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_constants.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/events/event.h" +#include "ui/events/event_constants.h" #include "ui/gfx/canvas.h" #include "ui/gfx/image/image.h" #include "ui/gfx/screen.h" #include "ui/views/controls/button/button.h" #include "ui/views/controls/button/menu_button_listener.h" +#include "ui/views/mouse_constants.h" #include "ui/views/widget/root_view.h" #include "ui/views/widget/widget.h" @@ -32,7 +33,6 @@ static const int kDefaultMenuOffsetY = -4; // static const char MenuButton::kViewClassName[] = "MenuButton"; -const int64 MenuButton::kMinimumTimeBetweenButtonClicks = 100; const int MenuButton::kMenuMarkerPaddingLeft = 3; const int MenuButton::kMenuMarkerPaddingRight = -1; @@ -182,10 +182,8 @@ bool MenuButton::OnMousePressed(const ui::MouseEvent& event) { HitTestPoint(event.location()) && GetDragOperations(event.location()) == ui::DragDropTypes::DRAG_NONE) { TimeDelta delta = Time::Now() - menu_closed_time_; - int64 delta_in_milliseconds = delta.InMilliseconds(); - if (delta_in_milliseconds > kMinimumTimeBetweenButtonClicks) { + if (delta.InMilliseconds() > kMinimumMsBetweenButtonClicks) return Activate(); - } } } return true; diff --git a/chromium/ui/views/controls/button/menu_button.h b/chromium/ui/views/controls/button/menu_button.h index 575942b1589..20cdb83316b 100644 --- a/chromium/ui/views/controls/button/menu_button.h +++ b/chromium/ui/views/controls/button/menu_button.h @@ -28,10 +28,6 @@ class VIEWS_EXPORT MenuButton : public TextButton { public: static const char kViewClassName[]; - // The amount of time, in milliseconds, we wait before allowing another mouse - // pressed event to show the menu. - static const int64 kMinimumTimeBetweenButtonClicks; - // How much padding to put on the left and right of the menu marker. static const int kMenuMarkerPaddingLeft; static const int kMenuMarkerPaddingRight; diff --git a/chromium/ui/views/controls/button/text_button.cc b/chromium/ui/views/controls/button/text_button.cc index a02d6b2b0fd..38e9691b19a 100644 --- a/chromium/ui/views/controls/button/text_button.cc +++ b/chromium/ui/views/controls/button/text_button.cc @@ -8,8 +8,8 @@ #include "base/logging.h" #include "grit/ui_resources.h" -#include "ui/base/animation/throb_animation.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/animation/throb_animation.h" #include "ui/gfx/canvas.h" #include "ui/gfx/image/image.h" #include "ui/views/controls/button/button.h" @@ -345,7 +345,7 @@ void TextButtonBase::OnBoundsChanged(const gfx::Rect& previous_bounds) { UpdateTextSize(); } -const ui::Animation* TextButtonBase::GetAnimation() const { +const gfx::Animation* TextButtonBase::GetAnimation() const { return hover_animation_.get(); } @@ -570,7 +570,7 @@ ui::NativeTheme::State TextButtonBase::GetThemeState( } } -const ui::Animation* TextButtonBase::GetThemeAnimation() const { +const gfx::Animation* TextButtonBase::GetThemeAnimation() const { #if defined(OS_WIN) if (GetNativeTheme() == ui::NativeThemeWin::instance()) { return ui::NativeThemeWin::instance()->IsThemingActive() ? diff --git a/chromium/ui/views/controls/button/text_button.h b/chromium/ui/views/controls/button/text_button.h index c66f288a241..5dccaa2ad11 100644 --- a/chromium/ui/views/controls/button/text_button.h +++ b/chromium/ui/views/controls/button/text_button.h @@ -142,7 +142,7 @@ class VIEWS_EXPORT TextButtonBase : public CustomButton, void set_alignment(TextAlignment alignment) { alignment_ = alignment; } - const ui::Animation* GetAnimation() const; + const gfx::Animation* GetAnimation() const; void SetIsDefault(bool is_default); bool is_default() const { return is_default_; } @@ -234,7 +234,7 @@ class VIEWS_EXPORT TextButtonBase : public CustomButton, virtual gfx::Rect GetThemePaintRect() const OVERRIDE; virtual ui::NativeTheme::State GetThemeState( ui::NativeTheme::ExtraParams* params) const OVERRIDE; - virtual const ui::Animation* GetThemeAnimation() const OVERRIDE; + virtual const gfx::Animation* GetThemeAnimation() const OVERRIDE; virtual ui::NativeTheme::State GetBackgroundThemeState( ui::NativeTheme::ExtraParams* params) const OVERRIDE; virtual ui::NativeTheme::State GetForegroundThemeState( diff --git a/chromium/ui/views/controls/combobox/combobox.cc b/chromium/ui/views/controls/combobox/combobox.cc index 34f48484755..8ef7b365e75 100644 --- a/chromium/ui/views/controls/combobox/combobox.cc +++ b/chromium/ui/views/controls/combobox/combobox.cc @@ -6,32 +6,101 @@ #include "base/logging.h" #include "base/strings/utf_string_conversions.h" +#include "grit/ui_resources.h" #include "ui/base/accessibility/accessible_view_state.h" -#include "ui/base/events/event.h" -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/base/models/combobox_model.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/keyboard_codes.h" +#include "ui/gfx/canvas.h" +#include "ui/native_theme/native_theme.h" +#include "ui/views/color_constants.h" #include "ui/views/controls/combobox/combobox_listener.h" -#include "ui/views/controls/native/native_view_host.h" +#include "ui/views/controls/focusable_border.h" +#include "ui/views/controls/menu/menu_runner.h" +#include "ui/views/controls/menu/submenu_view.h" #include "ui/views/controls/prefix_selector.h" #include "ui/views/ime/input_method.h" +#include "ui/views/mouse_constants.h" #include "ui/views/widget/widget.h" namespace views { +namespace { + +// Menu border widths +const int kMenuBorderWidthLeft = 1; +const int kMenuBorderWidthTop = 1; +const int kMenuBorderWidthRight = 1; +const int kMenuBorderWidthBottom = 2; + +// Limit how small a combobox can be. +const int kMinComboboxWidth = 25; + +// Size of the combobox arrow margins +const int kDisclosureArrowLeftPadding = 7; +const int kDisclosureArrowRightPadding = 7; + +// Define the id of the first item in the menu (since it needs to be > 0) +const int kFirstMenuItemId = 1000; + +const SkColor kInvalidTextColor = SK_ColorWHITE; + +// Used to indicate that no item is currently selected by the user. +const int kNoSelection = -1; + +// The background to use for invalid comboboxes. +class InvalidBackground : public Background { + public: + InvalidBackground() {} + virtual ~InvalidBackground() {} + + // Overridden from Background: + virtual void Paint(gfx::Canvas* canvas, View* view) const OVERRIDE { + gfx::Rect bounds(view->GetLocalBounds()); + // Inset by 2 to leave 1 empty pixel between background and border. + bounds.Inset(2, 2, 2, 2); + canvas->FillRect(bounds, kWarningColor); + } + + private: + DISALLOW_COPY_AND_ASSIGN(InvalidBackground); +}; + +// Returns the next or previous valid index (depending on |increment|'s value). +// Skips separator indices. Returns -1 if there is no valid adjacent index. +int GetAdjacentIndex(ui::ComboboxModel* model, int increment, int index) { + DCHECK(increment == -1 || increment == 1); + + index += increment; + while (index >= 0 && index < model->GetItemCount()) { + if (!model->IsItemSeparatorAt(index)) + return index; + index += increment; + } + return kNoSelection; +} + +} // namespace + // static -const char Combobox::kViewClassName[] = "Combobox"; +const char Combobox::kViewClassName[] = "views/Combobox"; //////////////////////////////////////////////////////////////////////////////// // Combobox, public: Combobox::Combobox(ui::ComboboxModel* model) - : native_wrapper_(NULL), - model_(model), + : model_(model), listener_(NULL), selected_index_(model_->GetDefaultIndex()), - invalid_(false) { + invalid_(false), + text_border_(new FocusableBorder()), + disclosure_arrow_(ui::ResourceBundle::GetSharedInstance().GetImageNamed( + IDR_MENU_DROPARROW).ToImageSkia()), + dropdown_open_(false) { + UpdateFromModel(); set_focusable(true); + set_border(text_border_); } Combobox::~Combobox() { @@ -45,22 +114,13 @@ const gfx::Font& Combobox::GetFont() { void Combobox::ModelChanged() { selected_index_ = std::min(0, model_->GetItemCount()); - if (native_wrapper_) - native_wrapper_->UpdateFromModel(); + UpdateFromModel(); PreferredSizeChanged(); } void Combobox::SetSelectedIndex(int index) { selected_index_ = index; - if (native_wrapper_) - native_wrapper_->UpdateSelectedIndex(); -} - -void Combobox::SelectionChanged() { - selected_index_ = native_wrapper_->GetSelectedIndex(); - if (listener_) - listener_->OnSelectedIndexChanged(this); - NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_VALUE_CHANGED, false); + SchedulePaint(); } void Combobox::SetAccessibleName(const string16& name) { @@ -69,8 +129,13 @@ void Combobox::SetAccessibleName(const string16& name) { void Combobox::SetInvalid(bool invalid) { invalid_ = invalid; - if (native_wrapper_) - native_wrapper_->ValidityStateChanged(); + if (invalid) { + text_border_->SetColor(kWarningColor); + set_background(new InvalidBackground()); + } else { + text_border_->UseDefaultColor(); + set_background(NULL); + } } ui::TextInputClient* Combobox::GetTextInputClient() { @@ -79,6 +144,28 @@ ui::TextInputClient* Combobox::GetTextInputClient() { return selector_.get(); } + +bool Combobox::IsItemChecked(int id) const { + return false; +} + +bool Combobox::IsCommandEnabled(int id) const { + return true; +} + +void Combobox::ExecuteCommand(int id) { + // (note that the id received is offset by kFirstMenuItemId) + // Revert menu ID offset to map back to combobox model. + id -= kFirstMenuItemId; + DCHECK_LT(id, model()->GetItemCount()); + selected_index_ = id; + OnSelectionChanged(); +} + +bool Combobox::GetAccelerator(int id, ui::Accelerator* accel) { + return false; +} + int Combobox::GetRowCount() { return model()->GetItemCount(); } @@ -99,65 +186,137 @@ string16 Combobox::GetTextForRow(int row) { // Combobox, View overrides: gfx::Size Combobox::GetPreferredSize() { - if (native_wrapper_) - return native_wrapper_->GetPreferredSize(); - return gfx::Size(); -} + if (content_size_.IsEmpty()) + UpdateFromModel(); -void Combobox::Layout() { - if (native_wrapper_) { - native_wrapper_->GetView()->SetBounds(0, 0, width(), height()); - native_wrapper_->GetView()->Layout(); - } + // The preferred size will drive the local bounds which in turn is used to set + // the minimum width for the dropdown list. + gfx::Insets insets = GetInsets(); + int total_width = std::max(kMinComboboxWidth, content_size_.width()) + + insets.width() + kDisclosureArrowLeftPadding + + disclosure_arrow_->width() + kDisclosureArrowRightPadding; + + return gfx::Size(total_width, content_size_.height() + insets.height()); } -void Combobox::OnEnabledChanged() { - View::OnEnabledChanged(); - if (native_wrapper_) - native_wrapper_->UpdateEnabled(); +const char* Combobox::GetClassName() const { + return kViewClassName; } -// VKEY_ESCAPE should be handled by this view when the drop down list is active. -// In other words, the list should be closed instead of the dialog. bool Combobox::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) { + // Escape should close the drop down list when it is active, not host UI. if (e.key_code() != ui::VKEY_ESCAPE || e.IsShiftDown() || e.IsControlDown() || e.IsAltDown()) { return false; } - return native_wrapper_ && native_wrapper_->IsDropdownOpen(); + return dropdown_open_; } -void Combobox::OnPaintFocusBorder(gfx::Canvas* canvas) { - if (NativeViewHost::kRenderNativeControlFocus) - View::OnPaintFocusBorder(canvas); +bool Combobox::OnMousePressed(const ui::MouseEvent& mouse_event) { + RequestFocus(); + const base::TimeDelta delta = base::Time::Now() - closed_time_; + if (mouse_event.IsLeftMouseButton() && + (delta.InMilliseconds() > kMinimumMsBetweenButtonClicks)) { + UpdateFromModel(); + ShowDropDownMenu(ui::MENU_SOURCE_MOUSE); + } + + return true; +} + +bool Combobox::OnMouseDragged(const ui::MouseEvent& mouse_event) { + return true; } bool Combobox::OnKeyPressed(const ui::KeyEvent& e) { - return native_wrapper_ && native_wrapper_->HandleKeyPressed(e); + // TODO(oshima): handle IME. + DCHECK_EQ(e.type(), ui::ET_KEY_PRESSED); + + DCHECK_GE(selected_index_, 0); + DCHECK_LT(selected_index_, model()->GetItemCount()); + if (selected_index_ < 0 || selected_index_ > model()->GetItemCount()) + selected_index_ = 0; + + bool show_menu = false; + int new_index = kNoSelection; + switch (e.key_code()) { + // Show the menu on Space. + case ui::VKEY_SPACE: + show_menu = true; + break; + + // Show the menu on Alt+Down (like Windows) or move to the next item if any. + case ui::VKEY_DOWN: + if (e.IsAltDown()) + show_menu = true; + else + new_index = GetAdjacentIndex(model(), 1, selected_index_); + break; + + // Move to the end of the list. + case ui::VKEY_END: + case ui::VKEY_NEXT: // Page down. + new_index = GetAdjacentIndex(model(), -1, model()->GetItemCount()); + break; + + // Move to the beginning of the list. + case ui::VKEY_HOME: + case ui::VKEY_PRIOR: // Page up. + new_index = GetAdjacentIndex(model(), 1, -1); + break; + + // Move to the previous item if any. + case ui::VKEY_UP: + new_index = GetAdjacentIndex(model(), -1, selected_index_); + break; + + default: + return false; + } + + if (show_menu) { + UpdateFromModel(); + ShowDropDownMenu(ui::MENU_SOURCE_KEYBOARD); + } else if (new_index != selected_index_ && new_index != kNoSelection) { + DCHECK(!model()->IsItemSeparatorAt(new_index)); + selected_index_ = new_index; + OnSelectionChanged(); + } + + return true; } bool Combobox::OnKeyReleased(const ui::KeyEvent& e) { - return native_wrapper_ && native_wrapper_->HandleKeyReleased(e); + return false; // crbug.com/127520 +} + +void Combobox::OnGestureEvent(ui::GestureEvent* gesture) { + if (gesture->type() == ui::ET_GESTURE_TAP) { + UpdateFromModel(); + ShowDropDownMenu(ui::MENU_SOURCE_TOUCH); + gesture->StopPropagation(); + return; + } + View::OnGestureEvent(gesture); +} + +void Combobox::OnPaint(gfx::Canvas* canvas) { + OnPaintBackground(canvas); + PaintText(canvas); + OnPaintBorder(canvas); } void Combobox::OnFocus() { GetInputMethod()->OnFocus(); - // Forward the focus to the wrapper. - if (native_wrapper_) { - native_wrapper_->SetFocus(); - NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_FOCUS, true); - } else { - View::OnFocus(); // Will focus the RootView window (so we still get - // keyboard messages). - } + text_border_->set_has_focus(true); + View::OnFocus(); } void Combobox::OnBlur() { GetInputMethod()->OnBlur(); if (selector_) selector_->OnViewBlur(); - if (native_wrapper_) - native_wrapper_->HandleBlur(); + text_border_->set_has_focus(false); } void Combobox::GetAccessibleState(ui::AccessibleViewState* state) { @@ -168,24 +327,129 @@ void Combobox::GetAccessibleState(ui::AccessibleViewState* state) { state->count = model_->GetItemCount(); } -void Combobox::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { - if (details.is_add && !native_wrapper_ && GetWidget()) { - // The native wrapper's lifetime will be managed by the view hierarchy after - // we call AddChildView. - native_wrapper_ = NativeComboboxWrapper::CreateWrapper(this); - AddChildView(native_wrapper_->GetView()); - // The underlying native widget may not be created until the wrapper is - // parented. For this reason the wrapper is only updated after adding its - // view. - native_wrapper_->UpdateFromModel(); - native_wrapper_->UpdateSelectedIndex(); - native_wrapper_->UpdateEnabled(); +void Combobox::UpdateFromModel() { + int max_width = 0; + const gfx::Font& font = Combobox::GetFont(); + + MenuItemView* menu = new MenuItemView(this); + // MenuRunner owns |menu|. + dropdown_list_menu_runner_.reset(new MenuRunner(menu)); + + int num_items = model()->GetItemCount(); + for (int i = 0; i < num_items; ++i) { + if (model()->IsItemSeparatorAt(i)) { + menu->AppendSeparator(); + continue; + } + + string16 text = model()->GetItemAt(i); + + // Inserting the Unicode formatting characters if necessary so that the + // text is displayed correctly in right-to-left UIs. + base::i18n::AdjustStringForLocaleDirection(&text); + + menu->AppendMenuItem(i + kFirstMenuItemId, text, MenuItemView::NORMAL); + max_width = std::max(max_width, font.GetStringWidth(text)); } + + content_size_.SetSize(max_width, font.GetHeight()); } -const char* Combobox::GetClassName() const { - return kViewClassName; +void Combobox::AdjustBoundsForRTLUI(gfx::Rect* rect) const { + rect->set_x(GetMirroredXForRect(*rect)); +} + +void Combobox::PaintText(gfx::Canvas* canvas) { + gfx::Insets insets = GetInsets(); + + canvas->Save(); + canvas->ClipRect(GetContentsBounds()); + + int x = insets.left(); + int y = insets.top(); + int text_height = height() - insets.height(); + SkColor text_color = invalid() ? kInvalidTextColor : + GetNativeTheme()->GetSystemColor( + ui::NativeTheme::kColorId_LabelEnabledColor); + + DCHECK_GE(selected_index_, 0); + DCHECK_LT(selected_index_, model()->GetItemCount()); + if (selected_index_ < 0 || selected_index_ > model()->GetItemCount()) + selected_index_ = 0; + string16 text = model()->GetItemAt(selected_index_); + + int disclosure_arrow_offset = width() - disclosure_arrow_->width() + - kDisclosureArrowLeftPadding - kDisclosureArrowRightPadding; + + const gfx::Font& font = Combobox::GetFont(); + int text_width = font.GetStringWidth(text); + if ((text_width + insets.width()) > disclosure_arrow_offset) + text_width = disclosure_arrow_offset - insets.width(); + + gfx::Rect text_bounds(x, y, text_width, text_height); + AdjustBoundsForRTLUI(&text_bounds); + canvas->DrawStringInt(text, font, text_color, text_bounds); + + gfx::Rect arrow_bounds(disclosure_arrow_offset + kDisclosureArrowLeftPadding, + height() / 2 - disclosure_arrow_->height() / 2, + disclosure_arrow_->width(), + disclosure_arrow_->height()); + AdjustBoundsForRTLUI(&arrow_bounds); + + SkPaint paint; + // This makes the arrow subtractive. + if (invalid()) + paint.setXfermodeMode(SkXfermode::kDstOut_Mode); + canvas->DrawImageInt(*disclosure_arrow_, arrow_bounds.x(), arrow_bounds.y(), + paint); + + canvas->Restore(); +} + +void Combobox::ShowDropDownMenu(ui::MenuSourceType source_type) { + if (!dropdown_list_menu_runner_.get()) + UpdateFromModel(); + + // Extend the menu to the width of the combobox. + MenuItemView* menu = dropdown_list_menu_runner_->GetMenu(); + SubmenuView* submenu = menu->CreateSubmenu(); + submenu->set_minimum_preferred_width(size().width() - + (kMenuBorderWidthLeft + kMenuBorderWidthRight)); + + gfx::Rect lb = GetLocalBounds(); + gfx::Point menu_position(lb.origin()); + + // Inset the menu's requested position so the border of the menu lines up + // with the border of the combobox. + menu_position.set_x(menu_position.x() + kMenuBorderWidthLeft); + menu_position.set_y(menu_position.y() + kMenuBorderWidthTop); + lb.set_width(lb.width() - (kMenuBorderWidthLeft + kMenuBorderWidthRight)); + + View::ConvertPointToScreen(this, &menu_position); + if (menu_position.x() < 0) + menu_position.set_x(0); + + gfx::Rect bounds(menu_position, lb.size()); + + dropdown_open_ = true; + if (dropdown_list_menu_runner_->RunMenuAt( + GetWidget(), NULL, bounds, MenuItemView::TOPLEFT, source_type, 0) == + MenuRunner::MENU_DELETED) + return; + dropdown_open_ = false; + closed_time_ = base::Time::Now(); + + // Need to explicitly clear mouse handler so that events get sent + // properly after the menu finishes running. If we don't do this, then + // the first click to other parts of the UI is eaten. + SetMouseHandler(NULL); +} + +void Combobox::OnSelectionChanged() { + if (listener_) + listener_->OnSelectedIndexChanged(this); + NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_VALUE_CHANGED, false); + SchedulePaint(); } } // namespace views diff --git a/chromium/ui/views/controls/combobox/combobox.h b/chromium/ui/views/controls/combobox/combobox.h index e71604e4238..09188e8e967 100644 --- a/chromium/ui/views/controls/combobox/combobox.h +++ b/chromium/ui/views/controls/combobox/combobox.h @@ -7,10 +7,10 @@ #include <string> +#include "base/time/time.h" #include "ui/gfx/native_widget_types.h" -#include "ui/views/controls/combobox/native_combobox_wrapper.h" +#include "ui/views/controls/menu/menu_delegate.h" #include "ui/views/controls/prefix_delegate.h" -#include "ui/views/view.h" namespace gfx { class Font; @@ -23,10 +23,12 @@ class ComboboxModel; namespace views { class ComboboxListener; +class FocusableBorder; +class MenuRunner; class PrefixSelector; -// A non-editable combobox (aka a drop-down list). -class VIEWS_EXPORT Combobox : public PrefixDelegate { +// A non-editable combobox (aka a drop-down list or selector). +class VIEWS_EXPORT Combobox : public MenuDelegate, public PrefixDelegate { public: // The combobox's class name. static const char kViewClassName[]; @@ -38,9 +40,7 @@ class VIEWS_EXPORT Combobox : public PrefixDelegate { static const gfx::Font& GetFont(); // Sets the listener which will be called when a selection has been made. - void set_listener(ComboboxListener* listener) { - listener_ = listener; - } + void set_listener(ComboboxListener* listener) { listener_ = listener; } // Informs the combobox that its model changed. void ModelChanged(); @@ -49,66 +49,67 @@ class VIEWS_EXPORT Combobox : public PrefixDelegate { int selected_index() const { return selected_index_; } void SetSelectedIndex(int index); - // Called when the combobox's selection is changed by the user. - void SelectionChanged(); - ui::ComboboxModel* model() const { return model_; } // Set the accessible name of the combobox. void SetAccessibleName(const string16& name); - // Provided only for testing: - gfx::NativeView GetTestingHandle() const { - return native_wrapper_ ? native_wrapper_->GetTestingHandle() : NULL; - } - NativeComboboxWrapper* GetNativeWrapperForTesting() const { - return native_wrapper_; - } - - // Visually marks the combobox as having an invalid value selected. The caller - // is responsible for flipping it back to valid if the selection changes. + // Visually marks the combobox as having an invalid value selected. + // When invalid, it paints with white text on a red background. + // Callers are responsible for restoring validity with selection changes. void SetInvalid(bool invalid); - - bool invalid() const { - return invalid_; - } + bool invalid() const { return invalid_; } // Overridden from View: virtual gfx::Size GetPreferredSize() OVERRIDE; - virtual void Layout() OVERRIDE; - virtual void OnEnabledChanged() OVERRIDE; + virtual const char* GetClassName() const OVERRIDE; virtual bool SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) OVERRIDE; - virtual void OnPaintFocusBorder(gfx::Canvas* canvas) OVERRIDE; + virtual bool OnMousePressed(const ui::MouseEvent& mouse_event) OVERRIDE; + virtual bool OnMouseDragged(const ui::MouseEvent& mouse_event) OVERRIDE; virtual bool OnKeyPressed(const ui::KeyEvent& e) OVERRIDE; virtual bool OnKeyReleased(const ui::KeyEvent& e) OVERRIDE; + virtual void OnGestureEvent(ui::GestureEvent* gesture) OVERRIDE; + virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; virtual void OnFocus() OVERRIDE; virtual void OnBlur() OVERRIDE; virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; virtual ui::TextInputClient* GetTextInputClient() OVERRIDE; + // Overridden from MenuDelegate: + virtual bool IsItemChecked(int id) const OVERRIDE; + virtual bool IsCommandEnabled(int id) const OVERRIDE; + virtual void ExecuteCommand(int id) OVERRIDE; + virtual bool GetAccelerator(int id, ui::Accelerator* accelerator) OVERRIDE; + // Overridden from PrefixDelegate: virtual int GetRowCount() OVERRIDE; virtual int GetSelectedRow() OVERRIDE; virtual void SetSelectedRow(int row) OVERRIDE; virtual string16 GetTextForRow(int row) OVERRIDE; - protected: - // Overridden from View: - virtual void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) OVERRIDE; - virtual const char* GetClassName() const OVERRIDE; + private: + // Updates the combobox's content from its model. + void UpdateFromModel(); - // The object that actually implements the native combobox. - NativeComboboxWrapper* native_wrapper_; + // Given bounds within our View, this helper mirrors the bounds if necessary. + void AdjustBoundsForRTLUI(gfx::Rect* rect) const; + + // Draw the selected value of the drop down list + void PaintText(gfx::Canvas* canvas); + + // Show the drop down list + void ShowDropDownMenu(ui::MenuSourceType source_type); + + // Called when the selection is changed by the user. + void OnSelectionChanged(); - private: // Our model. Not owned. ui::ComboboxModel* model_; // Our listener. Not owned. Notified when the selected index change. ComboboxListener* listener_; - // The current selected index. + // The current selected index; -1 and means no selection. int selected_index_; // True when the selection is visually denoted as invalid. @@ -117,8 +118,32 @@ class VIEWS_EXPORT Combobox : public PrefixDelegate { // The accessible name of this combobox. string16 accessible_name_; + // A helper used to select entries by keyboard input. scoped_ptr<PrefixSelector> selector_; + // The reference to the border class. The object is owned by View::border_. + FocusableBorder* text_border_; + + // The disclosure arrow next to the currently selected item from the list. + const gfx::ImageSkia* disclosure_arrow_; + + // Responsible for showing the context menu. + scoped_ptr<MenuRunner> dropdown_list_menu_runner_; + + // Is the drop down list showing + bool dropdown_open_; + + // Like MenuButton, we use a time object in order to keep track of when the + // combobox was closed. The time is used for simulating menu behavior; that + // is, if the menu is shown and the button is pressed, we need to close the + // menu. There is no clean way to get the second click event because the + // menu is displayed using a modal loop and, unlike regular menus in Windows, + // the button is not part of the displayed menu. + base::Time closed_time_; + + // The maximum dimensions of the content in the dropdown + gfx::Size content_size_; + DISALLOW_COPY_AND_ASSIGN(Combobox); }; diff --git a/chromium/ui/views/controls/combobox/combobox_unittest.cc b/chromium/ui/views/controls/combobox/combobox_unittest.cc new file mode 100644 index 00000000000..ea8d8f537bc --- /dev/null +++ b/chromium/ui/views/controls/combobox/combobox_unittest.cc @@ -0,0 +1,310 @@ +// 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 "ui/views/controls/combobox/combobox.h" + +#include <set> + +#include "base/strings/utf_string_conversions.h" +#include "ui/base/models/combobox_model.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/keyboard_codes.h" +#include "ui/views/ime/mock_input_method.h" +#include "ui/views/test/views_test_base.h" +#include "ui/views/widget/widget.h" + +namespace { + +// A wrapper of Combobox to intercept the result of OnKeyPressed() and +// OnKeyReleased() methods. +class TestCombobox : public views::Combobox { + public: + explicit TestCombobox(ui::ComboboxModel* model) + : Combobox(model), + key_handled_(false), + key_received_(false) { + } + + virtual bool OnKeyPressed(const ui::KeyEvent& e) OVERRIDE { + key_received_ = true; + key_handled_ = views::Combobox::OnKeyPressed(e); + return key_handled_; + } + + virtual bool OnKeyReleased(const ui::KeyEvent& e) OVERRIDE { + key_received_ = true; + key_handled_ = views::Combobox::OnKeyReleased(e); + return key_handled_; + } + + bool key_handled() const { return key_handled_; } + bool key_received() const { return key_received_; } + + void clear() { + key_received_ = key_handled_ = false; + } + + private: + bool key_handled_; + bool key_received_; + + DISALLOW_COPY_AND_ASSIGN(TestCombobox); +}; + +// A concrete class is needed to test the combobox. +class TestComboboxModel : public ui::ComboboxModel { + public: + TestComboboxModel() {} + virtual ~TestComboboxModel() {} + + // ui::ComboboxModel: + virtual int GetItemCount() const OVERRIDE { + return 10; + } + virtual string16 GetItemAt(int index) OVERRIDE { + return string16(); + } + virtual bool IsItemSeparatorAt(int index) OVERRIDE { + return separators_.find(index) != separators_.end(); + } + + void SetSeparators(const std::set<int>& separators) { + separators_ = separators; + } + + private: + std::set<int> separators_; + + DISALLOW_COPY_AND_ASSIGN(TestComboboxModel); +}; + +} // namespace + +namespace views { + +class ComboboxTest : public ViewsTestBase { + public: + ComboboxTest() : widget_(NULL), combobox_(NULL), input_method_(NULL) {} + + virtual void TearDown() OVERRIDE { + if (widget_) + widget_->Close(); + ViewsTestBase::TearDown(); + } + + void InitCombobox() { + model_.reset(new TestComboboxModel()); + + ASSERT_FALSE(combobox_); + combobox_ = new TestCombobox(model_.get()); + combobox_->set_id(1); + + widget_ = new Widget; + Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); + params.bounds = gfx::Rect(100, 100, 100, 100); + widget_->Init(params); + View* container = new View(); + widget_->SetContentsView(container); + container->AddChildView(combobox_); + + input_method_ = new MockInputMethod(); + widget_->ReplaceInputMethod(input_method_); + + // Assumes the Widget is always focused. + input_method_->OnFocus(); + + combobox_->RequestFocus(); + } + + protected: + void SendKeyEvent(ui::KeyboardCode key_code) { + ui::KeyEvent event(ui::ET_KEY_PRESSED, key_code, 0, false); + input_method_->DispatchKeyEvent(event); + } + + View* GetFocusedView() { + return widget_->GetFocusManager()->GetFocusedView(); + } + + // We need widget to populate wrapper class. + Widget* widget_; + + // |combobox_| will be allocated InitCombobox() and then owned by |widget_|. + TestCombobox* combobox_; + + // Combobox does not take ownership of the model, hence it needs to be scoped. + scoped_ptr<TestComboboxModel> model_; + + // For testing input method related behaviors. + MockInputMethod* input_method_; +}; + +TEST_F(ComboboxTest, KeyTest) { + InitCombobox(); + SendKeyEvent(ui::VKEY_END); + EXPECT_EQ(combobox_->selected_index() + 1, model_->GetItemCount()); + SendKeyEvent(ui::VKEY_HOME); + EXPECT_EQ(combobox_->selected_index(), 0); + SendKeyEvent(ui::VKEY_DOWN); + SendKeyEvent(ui::VKEY_DOWN); + EXPECT_EQ(combobox_->selected_index(), 2); + SendKeyEvent(ui::VKEY_RIGHT); + EXPECT_EQ(combobox_->selected_index(), 2); + SendKeyEvent(ui::VKEY_LEFT); + EXPECT_EQ(combobox_->selected_index(), 2); + SendKeyEvent(ui::VKEY_UP); + EXPECT_EQ(combobox_->selected_index(), 1); + SendKeyEvent(ui::VKEY_PRIOR); + EXPECT_EQ(combobox_->selected_index(), 0); + SendKeyEvent(ui::VKEY_NEXT); + EXPECT_EQ(combobox_->selected_index(), model_->GetItemCount() - 1); +} + +// Check that if a combobox is disabled before it has a native wrapper, then the +// native wrapper inherits the disabled state when it gets created. +TEST_F(ComboboxTest, DisabilityTest) { + model_.reset(new TestComboboxModel()); + + ASSERT_FALSE(combobox_); + combobox_ = new TestCombobox(model_.get()); + combobox_->SetEnabled(false); + + widget_ = new Widget; + Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); + params.bounds = gfx::Rect(100, 100, 100, 100); + widget_->Init(params); + View* container = new View(); + widget_->SetContentsView(container); + container->AddChildView(combobox_); + EXPECT_FALSE(combobox_->enabled()); +} + +// Verifies that we don't select a separator line in combobox when navigating +// through keyboard. +TEST_F(ComboboxTest, SkipSeparatorSimple) { + InitCombobox(); + std::set<int> separators; + separators.insert(2); + model_->SetSeparators(separators); + EXPECT_EQ(0, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_DOWN); + EXPECT_EQ(1, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_DOWN); + EXPECT_EQ(3, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_UP); + EXPECT_EQ(1, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_HOME); + EXPECT_EQ(0, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_PRIOR); + EXPECT_EQ(0, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_END); + EXPECT_EQ(9, combobox_->selected_index()); +} + +// Verifies that we never select the separator that is in the beginning of the +// combobox list when navigating through keyboard. +TEST_F(ComboboxTest, SkipSeparatorBeginning) { + InitCombobox(); + std::set<int> separators; + separators.insert(0); + model_->SetSeparators(separators); + EXPECT_EQ(0, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_DOWN); + EXPECT_EQ(1, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_DOWN); + EXPECT_EQ(2, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_UP); + EXPECT_EQ(1, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_HOME); + EXPECT_EQ(1, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_PRIOR); + EXPECT_EQ(1, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_END); + EXPECT_EQ(9, combobox_->selected_index()); +} + +// Verifies that we never select the separator that is in the end of the +// combobox list when navigating through keyboard. +TEST_F(ComboboxTest, SkipSeparatorEnd) { + InitCombobox(); + std::set<int> separators; + separators.insert(model_->GetItemCount() - 1); + model_->SetSeparators(separators); + combobox_->SetSelectedIndex(8); + SendKeyEvent(ui::VKEY_DOWN); + EXPECT_EQ(8, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_UP); + EXPECT_EQ(7, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_END); + EXPECT_EQ(8, combobox_->selected_index()); +} + +// Verifies that we never select any of the adjacent separators (multiple +// consecutive) that appear in the beginning of the combobox list when +// navigating through keyboard. +TEST_F(ComboboxTest, SkipMultipleSeparatorsAtBeginning) { + InitCombobox(); + std::set<int> separators; + separators.insert(0); + separators.insert(1); + separators.insert(2); + model_->SetSeparators(separators); + EXPECT_EQ(0, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_DOWN); + EXPECT_EQ(3, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_UP); + EXPECT_EQ(3, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_NEXT); + EXPECT_EQ(9, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_HOME); + EXPECT_EQ(3, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_END); + EXPECT_EQ(9, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_PRIOR); + EXPECT_EQ(3, combobox_->selected_index()); +} + +// Verifies that we never select any of the adjacent separators (multiple +// consecutive) that appear in the middle of the combobox list when navigating +// through keyboard. +TEST_F(ComboboxTest, SkipMultipleAdjacentSeparatorsAtMiddle) { + InitCombobox(); + std::set<int> separators; + separators.insert(4); + separators.insert(5); + separators.insert(6); + model_->SetSeparators(separators); + combobox_->SetSelectedIndex(3); + SendKeyEvent(ui::VKEY_DOWN); + EXPECT_EQ(7, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_UP); + EXPECT_EQ(3, combobox_->selected_index()); +} + +// Verifies that we never select any of the adjacent separators (multiple +// consecutive) that appear in the end of the combobox list when navigating +// through keyboard. +TEST_F(ComboboxTest, SkipMultipleSeparatorsAtEnd) { + InitCombobox(); + std::set<int> separators; + separators.insert(7); + separators.insert(8); + separators.insert(9); + model_->SetSeparators(separators); + combobox_->SetSelectedIndex(6); + SendKeyEvent(ui::VKEY_DOWN); + EXPECT_EQ(6, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_UP); + EXPECT_EQ(5, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_HOME); + EXPECT_EQ(0, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_NEXT); + EXPECT_EQ(6, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_PRIOR); + EXPECT_EQ(0, combobox_->selected_index()); + SendKeyEvent(ui::VKEY_END); + EXPECT_EQ(6, combobox_->selected_index()); +} + +} // namespace views diff --git a/chromium/ui/views/controls/combobox/native_combobox_views.cc b/chromium/ui/views/controls/combobox/native_combobox_views.cc deleted file mode 100644 index 3cb3a5c52a8..00000000000 --- a/chromium/ui/views/controls/combobox/native_combobox_views.cc +++ /dev/null @@ -1,435 +0,0 @@ -// Copyright (c) 2012 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 "ui/views/controls/combobox/native_combobox_views.h" - -#include <algorithm> - -#include "grit/ui_resources.h" -#include "ui/base/events/event.h" -#include "ui/base/keycodes/keyboard_codes.h" -#include "ui/base/models/combobox_model.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/font.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/path.h" -#include "ui/native_theme/native_theme.h" -#include "ui/views/background.h" -#include "ui/views/border.h" -#include "ui/views/color_constants.h" -#include "ui/views/controls/button/menu_button.h" -#include "ui/views/controls/combobox/combobox.h" -#include "ui/views/controls/focusable_border.h" -#include "ui/views/controls/menu/menu_runner.h" -#include "ui/views/controls/menu/submenu_view.h" -#include "ui/views/widget/root_view.h" -#include "ui/views/widget/widget.h" - -namespace views { - -namespace { - -// Define the size of the insets. -const int kTopInsetSize = 4; -const int kLeftInsetSize = 4; -const int kBottomInsetSize = 4; -const int kRightInsetSize = 4; - -// Menu border widths -const int kMenuBorderWidthLeft = 1; -const int kMenuBorderWidthTop = 1; -const int kMenuBorderWidthRight = 1; -const int kMenuBorderWidthBottom = 2; - -// Limit how small a combobox can be. -const int kMinComboboxWidth = 25; - -// Size of the combobox arrow margins -const int kDisclosureArrowLeftPadding = 7; -const int kDisclosureArrowRightPadding = 7; - -// Define the id of the first item in the menu (since it needs to be > 0) -const int kFirstMenuItemId = 1000; - -const SkColor kInvalidTextColor = SK_ColorWHITE; - -// The background to use for invalid comboboxes. -class InvalidBackground : public Background { - public: - InvalidBackground() {} - virtual ~InvalidBackground() {} - - // Overridden from Background: - virtual void Paint(gfx::Canvas* canvas, View* view) const OVERRIDE { - gfx::Rect bounds(view->GetLocalBounds()); - // Inset by 2 to leave 1 empty pixel between background and border. - bounds.Inset(2, 2, 2, 2); - canvas->FillRect(bounds, kWarningColor); - } - - private: - DISALLOW_COPY_AND_ASSIGN(InvalidBackground); -}; - -} // namespace - -const char NativeComboboxViews::kViewClassName[] = - "views/NativeComboboxViews"; - -NativeComboboxViews::NativeComboboxViews(Combobox* combobox) - : combobox_(combobox), - text_border_(new FocusableBorder()), - disclosure_arrow_(ui::ResourceBundle::GetSharedInstance().GetImageNamed( - IDR_MENU_DROPARROW).ToImageSkia()), - dropdown_open_(false), - selected_index_(-1), - content_width_(0), - content_height_(0) { - set_border(text_border_); -} - -NativeComboboxViews::~NativeComboboxViews() { -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeComboboxViews, View overrides: - -bool NativeComboboxViews::OnMousePressed(const ui::MouseEvent& mouse_event) { - combobox_->RequestFocus(); - const base::TimeDelta delta = base::Time::Now() - closed_time_; - if (mouse_event.IsLeftMouseButton() && - (delta.InMilliseconds() > MenuButton::kMinimumTimeBetweenButtonClicks)) { - UpdateFromModel(); - ShowDropDownMenu(ui::MENU_SOURCE_MOUSE); - } - - return true; -} - -bool NativeComboboxViews::OnMouseDragged(const ui::MouseEvent& mouse_event) { - return true; -} - -bool NativeComboboxViews::OnKeyPressed(const ui::KeyEvent& key_event) { - // TODO(oshima): handle IME. - DCHECK_EQ(key_event.type(), ui::ET_KEY_PRESSED); - - // Check if we are in the default state (-1) and set to first item. - if (selected_index_ == -1) - selected_index_ = 0; - - bool show_menu = false; - int new_index = selected_index_; - switch (key_event.key_code()) { - // Show the menu on Space. - case ui::VKEY_SPACE: - show_menu = true; - break; - - // Show the menu on Alt+Down (like Windows) or move to the next item if any. - case ui::VKEY_DOWN: - if (key_event.IsAltDown()) - show_menu = true; - else if (new_index < (combobox_->model()->GetItemCount() - 1)) - new_index++; - break; - - // Move to the end of the list. - case ui::VKEY_END: - case ui::VKEY_NEXT: - new_index = combobox_->model()->GetItemCount() - 1; - break; - - // Move to the beginning of the list. - case ui::VKEY_HOME: - case ui::VKEY_PRIOR: - new_index = 0; - break; - - // Move to the previous item if any. - case ui::VKEY_UP: - if (new_index > 0) - new_index--; - break; - - default: - return false; - } - - if (show_menu) { - UpdateFromModel(); - ShowDropDownMenu(ui::MENU_SOURCE_KEYBOARD); - } else if (new_index != selected_index_) { - selected_index_ = new_index; - combobox_->SelectionChanged(); - SchedulePaint(); - } - - return true; -} - -bool NativeComboboxViews::OnKeyReleased(const ui::KeyEvent& key_event) { - return true; -} - -void NativeComboboxViews::OnPaint(gfx::Canvas* canvas) { - text_border_->set_has_focus(combobox_->HasFocus()); - OnPaintBackground(canvas); - PaintText(canvas); - OnPaintBorder(canvas); -} - -void NativeComboboxViews::OnFocus() { - NOTREACHED(); -} - -void NativeComboboxViews::OnBlur() { - NOTREACHED(); -} - -///////////////////////////////////////////////////////////////// -// NativeComboboxViews, ui::EventHandler overrides: - -void NativeComboboxViews::OnGestureEvent(ui::GestureEvent* gesture) { - if (gesture->type() == ui::ET_GESTURE_TAP) { - UpdateFromModel(); - ShowDropDownMenu(ui::MENU_SOURCE_TOUCH); - gesture->StopPropagation(); - return; - } - View::OnGestureEvent(gesture); -} - -///////////////////////////////////////////////////////////////// -// NativeComboboxViews, NativeComboboxWrapper overrides: - -void NativeComboboxViews::UpdateFromModel() { - int max_width = 0; - const gfx::Font& font = Combobox::GetFont(); - - MenuItemView* menu = new MenuItemView(this); - // MenuRunner owns |menu|. - dropdown_list_menu_runner_.reset(new MenuRunner(menu)); - - int num_items = combobox_->model()->GetItemCount(); - for (int i = 0; i < num_items; ++i) { - if (combobox_->model()->IsItemSeparatorAt(i)) { - menu->AppendSeparator(); - continue; - } - - string16 text = combobox_->model()->GetItemAt(i); - - // Inserting the Unicode formatting characters if necessary so that the - // text is displayed correctly in right-to-left UIs. - base::i18n::AdjustStringForLocaleDirection(&text); - - menu->AppendMenuItem(i + kFirstMenuItemId, text, MenuItemView::NORMAL); - max_width = std::max(max_width, font.GetStringWidth(text)); - } - - content_width_ = max_width; - content_height_ = font.GetHeight(); -} - -void NativeComboboxViews::UpdateSelectedIndex() { - selected_index_ = combobox_->selected_index(); - SchedulePaint(); -} - -void NativeComboboxViews::UpdateEnabled() { - SetEnabled(combobox_->enabled()); -} - -int NativeComboboxViews::GetSelectedIndex() const { - return selected_index_; -} - -bool NativeComboboxViews::IsDropdownOpen() const { - return dropdown_open_; -} - -gfx::Size NativeComboboxViews::GetPreferredSize() { - if (content_width_ == 0) - UpdateFromModel(); - - // The preferred size will drive the local bounds which in turn is used to set - // the minimum width for the dropdown list. - gfx::Insets insets = GetInsets(); - int total_width = std::max(kMinComboboxWidth, content_width_) + - insets.width() + kDisclosureArrowLeftPadding + - disclosure_arrow_->width() + kDisclosureArrowRightPadding; - - return gfx::Size(total_width, content_height_ + insets.height()); -} - -View* NativeComboboxViews::GetView() { - return this; -} - -void NativeComboboxViews::SetFocus() { - text_border_->set_has_focus(true); -} - -void NativeComboboxViews::ValidityStateChanged() { - if (combobox_->invalid()) { - text_border_->SetColor(kWarningColor); - set_background(new InvalidBackground()); - } else { - text_border_->UseDefaultColor(); - set_background(NULL); - } - SchedulePaint(); -} - -bool NativeComboboxViews::HandleKeyPressed(const ui::KeyEvent& e) { - return OnKeyPressed(e); -} - -bool NativeComboboxViews::HandleKeyReleased(const ui::KeyEvent& e) { - return false; // crbug.com/127520 -} - -void NativeComboboxViews::HandleFocus() { - SchedulePaint(); -} - -void NativeComboboxViews::HandleBlur() { -} - -gfx::NativeView NativeComboboxViews::GetTestingHandle() const { - NOTREACHED(); - return NULL; -} - -///////////////////////////////////////////////////////////////// -// NativeComboboxViews, views::MenuDelegate overrides: -// (note that the id received is offset by kFirstMenuItemId) - -bool NativeComboboxViews::IsItemChecked(int id) const { - return false; -} - -bool NativeComboboxViews::IsCommandEnabled(int id) const { - return true; -} - -void NativeComboboxViews::ExecuteCommand(int id) { - // Revert menu offset to map back to combobox model. - id -= kFirstMenuItemId; - DCHECK_LT(id, combobox_->model()->GetItemCount()); - selected_index_ = id; - combobox_->SelectionChanged(); - SchedulePaint(); -} - -bool NativeComboboxViews::GetAccelerator(int id, ui::Accelerator* accel) { - return false; -} - -///////////////////////////////////////////////////////////////// -// NativeComboboxViews private methods: - -void NativeComboboxViews::AdjustBoundsForRTLUI(gfx::Rect* rect) const { - rect->set_x(GetMirroredXForRect(*rect)); -} - -void NativeComboboxViews::PaintText(gfx::Canvas* canvas) { - gfx::Insets insets = GetInsets(); - - canvas->Save(); - canvas->ClipRect(GetContentsBounds()); - - int x = insets.left(); - int y = insets.top(); - int text_height = height() - insets.height(); - SkColor text_color = combobox_->invalid() ? kInvalidTextColor : - GetNativeTheme()->GetSystemColor( - ui::NativeTheme::kColorId_LabelEnabledColor); - - int index = GetSelectedIndex(); - if (index < 0 || index > combobox_->model()->GetItemCount()) - index = 0; - string16 text = combobox_->model()->GetItemAt(index); - - int disclosure_arrow_offset = width() - disclosure_arrow_->width() - - kDisclosureArrowLeftPadding - kDisclosureArrowRightPadding; - - const gfx::Font& font = Combobox::GetFont(); - int text_width = font.GetStringWidth(text); - if ((text_width + insets.width()) > disclosure_arrow_offset) - text_width = disclosure_arrow_offset - insets.width(); - - gfx::Rect text_bounds(x, y, text_width, text_height); - AdjustBoundsForRTLUI(&text_bounds); - canvas->DrawStringInt(text, font, text_color, text_bounds); - - gfx::Rect arrow_bounds(disclosure_arrow_offset + kDisclosureArrowLeftPadding, - height() / 2 - disclosure_arrow_->height() / 2, - disclosure_arrow_->width(), - disclosure_arrow_->height()); - AdjustBoundsForRTLUI(&arrow_bounds); - - SkPaint paint; - // This makes the arrow subtractive. - if (combobox_->invalid()) - paint.setXfermodeMode(SkXfermode::kDstOut_Mode); - canvas->DrawImageInt(*disclosure_arrow_, arrow_bounds.x(), arrow_bounds.y(), - paint); - - canvas->Restore(); -} - -void NativeComboboxViews::ShowDropDownMenu(ui::MenuSourceType source_type) { - if (!dropdown_list_menu_runner_.get()) - UpdateFromModel(); - - // Extend the menu to the width of the combobox. - MenuItemView* menu = dropdown_list_menu_runner_->GetMenu(); - SubmenuView* submenu = menu->CreateSubmenu(); - submenu->set_minimum_preferred_width(size().width() - - (kMenuBorderWidthLeft + kMenuBorderWidthRight)); - - gfx::Rect lb = GetLocalBounds(); - gfx::Point menu_position(lb.origin()); - - // Inset the menu's requested position so the border of the menu lines up - // with the border of the combobox. - menu_position.set_x(menu_position.x() + kMenuBorderWidthLeft); - menu_position.set_y(menu_position.y() + kMenuBorderWidthTop); - lb.set_width(lb.width() - (kMenuBorderWidthLeft + kMenuBorderWidthRight)); - - View::ConvertPointToScreen(this, &menu_position); - if (menu_position.x() < 0) - menu_position.set_x(0); - - gfx::Rect bounds(menu_position, lb.size()); - - dropdown_open_ = true; - if (dropdown_list_menu_runner_->RunMenuAt( - GetWidget(), NULL, bounds, MenuItemView::TOPLEFT, source_type, 0) == - MenuRunner::MENU_DELETED) - return; - dropdown_open_ = false; - closed_time_ = base::Time::Now(); - - // Need to explicitly clear mouse handler so that events get sent - // properly after the menu finishes running. If we don't do this, then - // the first click to other parts of the UI is eaten. - SetMouseHandler(NULL); -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeComboboxWrapper, public: - -#if defined(USE_AURA) -// static -NativeComboboxWrapper* NativeComboboxWrapper::CreateWrapper( - Combobox* combobox) { - return new NativeComboboxViews(combobox); -} -#endif - -} // namespace views diff --git a/chromium/ui/views/controls/combobox/native_combobox_views.h b/chromium/ui/views/controls/combobox/native_combobox_views.h deleted file mode 100644 index bdf70339acf..00000000000 --- a/chromium/ui/views/controls/combobox/native_combobox_views.h +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef UI_VIEWS_CONTROLS_COMBOBOX_NATIVE_COMBOBOX_VIEWS_H_ -#define UI_VIEWS_CONTROLS_COMBOBOX_NATIVE_COMBOBOX_VIEWS_H_ - -#include "base/time/time.h" -#include "ui/views/controls/combobox/native_combobox_wrapper.h" -#include "ui/views/controls/menu/menu_delegate.h" -#include "ui/views/view.h" - -namespace gfx { -class Canvas; -class Font; -} - -namespace views { - -class FocusableBorder; -class MenuRunner; - -// A views/skia only implementation of NativeComboboxWrapper. -// No platform specific code is used. -class NativeComboboxViews : public views::View, - public NativeComboboxWrapper, - public views::MenuDelegate { - public: - static const char kViewClassName[]; - - explicit NativeComboboxViews(Combobox* combobox); - virtual ~NativeComboboxViews(); - - // views::View overrides: - virtual bool OnMousePressed(const ui::MouseEvent& mouse_event) OVERRIDE; - virtual bool OnMouseDragged(const ui::MouseEvent& mouse_event) OVERRIDE; - virtual bool OnKeyPressed(const ui::KeyEvent& key_event) OVERRIDE; - virtual bool OnKeyReleased(const ui::KeyEvent& key_event) OVERRIDE; - virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; - virtual void OnFocus() OVERRIDE; - virtual void OnBlur() OVERRIDE; - - // ui::EventHandler overrides: - virtual void OnGestureEvent(ui::GestureEvent* gesture) OVERRIDE; - - // NativeComboboxWrapper overrides: - virtual void UpdateFromModel() OVERRIDE; - virtual void UpdateSelectedIndex() OVERRIDE; - virtual void UpdateEnabled() OVERRIDE; - virtual int GetSelectedIndex() const OVERRIDE; - virtual bool IsDropdownOpen() const OVERRIDE; - virtual gfx::Size GetPreferredSize() OVERRIDE; - virtual View* GetView() OVERRIDE; - virtual void SetFocus() OVERRIDE; - virtual void ValidityStateChanged() OVERRIDE; - virtual bool HandleKeyPressed(const ui::KeyEvent& event) OVERRIDE; - virtual bool HandleKeyReleased(const ui::KeyEvent& event) OVERRIDE; - virtual void HandleFocus() OVERRIDE; - virtual void HandleBlur() OVERRIDE; - virtual gfx::NativeView GetTestingHandle() const OVERRIDE; - - // MenuDelegate overrides: - virtual bool IsItemChecked(int id) const OVERRIDE; - virtual bool IsCommandEnabled(int id) const OVERRIDE; - virtual void ExecuteCommand(int id) OVERRIDE; - virtual bool GetAccelerator(int id, ui::Accelerator* accelerator) OVERRIDE; - - private: - // Given bounds within our View, this helper routine mirrors the bounds if - // necessary. - void AdjustBoundsForRTLUI(gfx::Rect* rect) const; - - // Draw the selected value of the drop down list - void PaintText(gfx::Canvas* canvas); - - // Show the drop down list - void ShowDropDownMenu(ui::MenuSourceType source_type); - - // The parent combobox, the owner of this object. - Combobox* combobox_; - - // The reference to the border class. The object is owned by View::border_. - FocusableBorder* text_border_; - - // The disclosure arrow next to the currently selected item from the list. - const gfx::ImageSkia* disclosure_arrow_; - - // Responsible for showing the context menu. - scoped_ptr<MenuRunner> dropdown_list_menu_runner_; - - // Is the drop down list showing - bool dropdown_open_; - - // Like MenuButton, we use a time object in order to keep track of when the - // combobox was closed. The time is used for simulating menu behavior; that - // is, if the menu is shown and the button is pressed, we need to close the - // menu. There is no clean way to get the second click event because the - // menu is displayed using a modal loop and, unlike regular menus in Windows, - // the button is not part of the displayed menu. - base::Time closed_time_; - - // The selected index in the model. The default value is -1, which means no - // selection. - int selected_index_; - - // The maximum dimensions of the content in the dropdown - int content_width_; - int content_height_; - - DISALLOW_COPY_AND_ASSIGN(NativeComboboxViews); -}; - -} // namespace views - -#endif // UI_VIEWS_CONTROLS_COMBOBOX_NATIVE_COMBOBOX_VIEWS_H_ diff --git a/chromium/ui/views/controls/combobox/native_combobox_views_unittest.cc b/chromium/ui/views/controls/combobox/native_combobox_views_unittest.cc deleted file mode 100644 index 66811dd19a2..00000000000 --- a/chromium/ui/views/controls/combobox/native_combobox_views_unittest.cc +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright (c) 2012 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 "base/strings/utf_string_conversions.h" -#include "ui/base/events/event.h" -#include "ui/base/keycodes/keyboard_codes.h" -#include "ui/base/models/combobox_model.h" -#include "ui/views/controls/combobox/combobox.h" -#include "ui/views/controls/combobox/native_combobox_views.h" -#include "ui/views/ime/mock_input_method.h" -#include "ui/views/test/views_test_base.h" -#include "ui/views/widget/native_widget_private.h" -#include "ui/views/widget/widget.h" - -namespace { - -// A wrapper of Combobox to intercept the result of OnKeyPressed() and -// OnKeyReleased() methods. -class TestCombobox : public views::Combobox { - public: - explicit TestCombobox(ui::ComboboxModel* model) - : Combobox(model), - key_handled_(false), - key_received_(false) { - } - - virtual bool OnKeyPressed(const ui::KeyEvent& e) OVERRIDE { - key_received_ = true; - key_handled_ = views::Combobox::OnKeyPressed(e); - return key_handled_; - } - - virtual bool OnKeyReleased(const ui::KeyEvent& e) OVERRIDE { - key_received_ = true; - key_handled_ = views::Combobox::OnKeyReleased(e); - return key_handled_; - } - - bool key_handled() const { return key_handled_; } - bool key_received() const { return key_received_; } - - void clear() { - key_received_ = key_handled_ = false; - } - - private: - bool key_handled_; - bool key_received_; - - DISALLOW_COPY_AND_ASSIGN(TestCombobox); -}; - -// A concrete class is needed to test the combobox. -class TestComboboxModel : public ui::ComboboxModel { - public: - TestComboboxModel() {} - virtual ~TestComboboxModel() {} - - // Overridden from ui::ComboboxModel: - virtual int GetItemCount() const OVERRIDE { - return 4; - } - virtual string16 GetItemAt(int index) OVERRIDE { - return string16(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(TestComboboxModel); -}; - -} // namespace - -namespace views { - -class NativeComboboxViewsTest : public ViewsTestBase { - public: - NativeComboboxViewsTest() - : widget_(NULL), - combobox_(NULL), - combobox_view_(NULL), - input_method_(NULL) {} - - // ::testing::Test: - virtual void SetUp() { - ViewsTestBase::SetUp(); - } - - virtual void TearDown() { - if (widget_) - widget_->Close(); - ViewsTestBase::TearDown(); - } - - void InitCombobox() { - model_.reset(new TestComboboxModel()); - - ASSERT_FALSE(combobox_); - combobox_ = new TestCombobox(model_.get()); - combobox_->set_id(1); - - widget_ = new Widget; - Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); - params.bounds = gfx::Rect(100, 100, 100, 100); - widget_->Init(params); - View* container = new View(); - widget_->SetContentsView(container); - container->AddChildView(combobox_); - - combobox_view_ = static_cast<NativeComboboxViews*>( - combobox_->GetNativeWrapperForTesting()); - ASSERT_TRUE(combobox_view_); - - input_method_ = new MockInputMethod(); - widget_->ReplaceInputMethod(input_method_); - - // Assumes the Widget is always focused. - input_method_->OnFocus(); - - combobox_->RequestFocus(); - } - - protected: - void SendKeyEvent(ui::KeyboardCode key_code) { - ui::KeyEvent event(ui::ET_KEY_PRESSED, key_code, 0, false); - input_method_->DispatchKeyEvent(event); - } - - View* GetFocusedView() { - return widget_->GetFocusManager()->GetFocusedView(); - } - - // We need widget to populate wrapper class. - Widget* widget_; - - // |combobox_| will be allocated InitCombobox() and then owned by |widget_|. - TestCombobox* combobox_; - - // |combobox_view_| is the pointer to the pure Views interface of |combobox_|. - NativeComboboxViews* combobox_view_; - - // Combobox does not take ownership of the model, hence it needs to be scoped. - scoped_ptr<TestComboboxModel> model_; - - // For testing input method related behaviors. - MockInputMethod* input_method_; -}; - -TEST_F(NativeComboboxViewsTest, KeyTest) { - InitCombobox(); - SendKeyEvent(ui::VKEY_END); - EXPECT_EQ(combobox_->selected_index() + 1, model_->GetItemCount()); - SendKeyEvent(ui::VKEY_HOME); - EXPECT_EQ(combobox_->selected_index(), 0); - SendKeyEvent(ui::VKEY_DOWN); - SendKeyEvent(ui::VKEY_DOWN); - EXPECT_EQ(combobox_->selected_index(), 2); - SendKeyEvent(ui::VKEY_RIGHT); - EXPECT_EQ(combobox_->selected_index(), 2); - SendKeyEvent(ui::VKEY_LEFT); - EXPECT_EQ(combobox_->selected_index(), 2); - SendKeyEvent(ui::VKEY_UP); - EXPECT_EQ(combobox_->selected_index(), 1); - SendKeyEvent(ui::VKEY_PRIOR); - EXPECT_EQ(combobox_->selected_index(), 0); - SendKeyEvent(ui::VKEY_NEXT); - EXPECT_EQ(combobox_->selected_index(), model_->GetItemCount() - 1); -} - -// Check that if a combobox is disabled before it has a native wrapper, then the -// native wrapper inherits the disabled state when it gets created. -TEST_F(NativeComboboxViewsTest, DisabilityTest) { - model_.reset(new TestComboboxModel()); - - ASSERT_FALSE(combobox_); - combobox_ = new TestCombobox(model_.get()); - combobox_->SetEnabled(false); - ASSERT_FALSE(combobox_->GetNativeWrapperForTesting()); - - widget_ = new Widget; - Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); - params.bounds = gfx::Rect(100, 100, 100, 100); - widget_->Init(params); - View* container = new View(); - widget_->SetContentsView(container); - container->AddChildView(combobox_); - - combobox_view_ = static_cast<NativeComboboxViews*>( - combobox_->GetNativeWrapperForTesting()); - ASSERT_TRUE(combobox_view_); - ASSERT_FALSE(combobox_view_->enabled()); -} - -} // namespace views diff --git a/chromium/ui/views/controls/combobox/native_combobox_win.cc b/chromium/ui/views/controls/combobox/native_combobox_win.cc deleted file mode 100644 index 3093c53bc22..00000000000 --- a/chromium/ui/views/controls/combobox/native_combobox_win.cc +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright (c) 2012 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 "ui/views/controls/combobox/native_combobox_win.h" - -#include "base/i18n/rtl.h" -#include "base/strings/utf_string_conversions.h" -#include "ui/base/events/event.h" -#include "ui/base/models/combobox_model.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/base/win/hwnd_util.h" -#include "ui/gfx/font.h" -#include "ui/native_theme/native_theme_win.h" -#include "ui/views/controls/combobox/combobox.h" -#include "ui/views/controls/combobox/native_combobox_views.h" -#include "ui/views/widget/widget.h" - -namespace { - -// Limit how small a combobox can be. -const int kMinComboboxWidth = 148; - -// Add a couple extra pixels to the widths of comboboxes and combobox -// dropdowns so that text isn't too crowded. -const int kComboboxExtraPaddingX = 6; - -} // namespace - -namespace views { - -//////////////////////////////////////////////////////////////////////////////// -// NativeComboboxWin, public: - -NativeComboboxWin::NativeComboboxWin(Combobox* combobox) - : combobox_(combobox), - content_width_(0) { - // Associates the actual HWND with the combobox so it is the one considered as - // having the focus (not the wrapper) when the HWND is focused directly (with - // a click for example). - set_focus_view(combobox); -} - -NativeComboboxWin::~NativeComboboxWin() { -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeComboboxWin, NativeComboboxWrapper implementation: - -void NativeComboboxWin::UpdateFromModel() { - SendMessage(native_view(), CB_RESETCONTENT, 0, 0); - const gfx::Font& font = Combobox::GetFont(); - int max_width = 0; - int num_items = combobox_->model()->GetItemCount(); - for (int i = 0; i < num_items; ++i) { - string16 text = combobox_->model()->GetItemAt(i); - - // Inserting the Unicode formatting characters if necessary so that the - // text is displayed correctly in right-to-left UIs. - base::i18n::AdjustStringForLocaleDirection(&text); - - SendMessage(native_view(), CB_ADDSTRING, 0, - reinterpret_cast<LPARAM>(UTF16ToWide(text).c_str())); - max_width = std::max(max_width, font.GetStringWidth(text)); - } - content_width_ = max_width; - - if (num_items > 0) { - SendMessage(native_view(), CB_SETCURSEL, combobox_->selected_index(), 0); - - // Set the width for the drop down while accounting for the scrollbar and - // borders. - if (num_items > ComboBox_GetMinVisible(native_view())) - max_width += GetSystemMetrics(SM_CXVSCROLL); - // SM_CXEDGE would not be correct here, since the dropdown is flat, not 3D. - int kComboboxDropdownBorderSize = 1; - max_width += 2 * kComboboxDropdownBorderSize + kComboboxExtraPaddingX; - SendMessage(native_view(), CB_SETDROPPEDWIDTH, max_width, 0); - } -} - -void NativeComboboxWin::UpdateSelectedIndex() { - // Note that we use CB_SETCURSEL and not CB_SELECTSTRING because on RTL - // locales the strings we get from our ComboBox::Model might be augmented - // with Unicode directionality marks before we insert them into the combobox - // and therefore we can not assume that the string we get from - // ui::ComboboxModel can be safely searched for and selected (which is what - // CB_SELECTSTRING does). - SendMessage(native_view(), CB_SETCURSEL, combobox_->selected_index(), 0); -} - -void NativeComboboxWin::UpdateEnabled() { - SetEnabled(combobox_->enabled()); -} - -int NativeComboboxWin::GetSelectedIndex() const { - LRESULT selected_index = SendMessage(native_view(), CB_GETCURSEL, 0, 0); - return selected_index != CB_ERR ? selected_index : -1; -} - -bool NativeComboboxWin::IsDropdownOpen() const { - return SendMessage(native_view(), CB_GETDROPPEDSTATE, 0, 0) != 0; -} - -gfx::Size NativeComboboxWin::GetPreferredSize() { - COMBOBOXINFO cbi = { 0 }; - cbi.cbSize = sizeof(cbi); - // Note: Don't use CB_GETCOMBOBOXINFO since that crashes on WOW64 systems - // when you have a global message hook installed. - GetComboBoxInfo(native_view(), &cbi); - gfx::Rect rect_item(cbi.rcItem); - gfx::Rect rect_button(cbi.rcButton); - gfx::Size border = ui::NativeThemeWin::instance()->GetThemeBorderSize( - ui::NativeThemeWin::MENULIST); - - // The padding value of '3' is the xy offset from the corner of the control - // to the corner of rcItem. It does not seem to be queryable from the theme. - // It is consistent on all versions of Windows from 2K to Vista, and is - // invariant with respect to the combobox border size. We could conceivably - // get this number from rect_item.x, but it seems fragile to depend on - // position here, inside of the layout code. - const int kItemOffset = 3; - int item_to_button_distance = std::max(kItemOffset - border.width(), 0); - - // The cx computation can be read as measuring from left to right. - int pref_width = std::max(kItemOffset + content_width_ + - kComboboxExtraPaddingX + - item_to_button_distance + rect_button.width() + - border.width(), kMinComboboxWidth); - // The two arguments to ::max below should be typically be equal. - int pref_height = std::max(rect_item.height() + 2 * kItemOffset, - rect_button.height() + 2 * border.height()); - return gfx::Size(pref_width, pref_height); -} - -View* NativeComboboxWin::GetView() { - return this; -} - -void NativeComboboxWin::SetFocus() { - OnFocus(); -} - -void NativeComboboxWin::ValidityStateChanged() { - // TODO(estade): implement. -} - -bool NativeComboboxWin::HandleKeyPressed(const ui::KeyEvent& event) { - return false; -} - -bool NativeComboboxWin::HandleKeyReleased(const ui::KeyEvent& event) { - return false; -} - -void NativeComboboxWin::HandleFocus() { -} - -void NativeComboboxWin::HandleBlur() { -} - -gfx::NativeView NativeComboboxWin::GetTestingHandle() const { - return native_view(); -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeComboboxWin, NativeControlWin overrides: - -bool NativeComboboxWin::ProcessMessage(UINT message, - WPARAM w_param, - LPARAM l_param, - LRESULT* result) { - if (message == WM_COMMAND && HIWORD(w_param) == CBN_SELCHANGE) { - combobox_->SelectionChanged(); - *result = 0; - return true; - } - return NativeControlWin::ProcessMessage(message, w_param, l_param, result); -} - -void NativeComboboxWin::CreateNativeControl() { - // It's ok to add WS_VSCROLL. The scrollbar will show up only when necessary - // as long as we don't use CBS_DISABLENOSCROLL. - // See http://msdn.microsoft.com/en-us/library/7h63bxbe(VS.80).aspx - DWORD flags = WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | - CBS_DROPDOWNLIST | WS_VSCROLL; - HWND control_hwnd = ::CreateWindowEx(GetAdditionalExStyle(), L"COMBOBOX", L"", - flags, 0, 0, width(), height(), - GetWidget()->GetNativeView(), NULL, NULL, - NULL); - ui::CheckWindowCreated(control_hwnd); - NativeControlCreated(control_hwnd); -} - -void NativeComboboxWin::NativeControlCreated(HWND native_control) { - NativeControlWin::NativeControlCreated(native_control); - - UpdateFont(); -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeComboboxWin, private: - -void NativeComboboxWin::UpdateFont() { - HFONT font = Combobox::GetFont().GetNativeFont(); - SendMessage(native_view(), WM_SETFONT, reinterpret_cast<WPARAM>(font), FALSE); -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeComboboxWrapper, public: - -// static -NativeComboboxWrapper* NativeComboboxWrapper::CreateWrapper( - Combobox* combobox) { - return new NativeComboboxViews(combobox); -} - -} // namespace views diff --git a/chromium/ui/views/controls/combobox/native_combobox_win.h b/chromium/ui/views/controls/combobox/native_combobox_win.h deleted file mode 100644 index 534946009a4..00000000000 --- a/chromium/ui/views/controls/combobox/native_combobox_win.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef UI_VIEWS_CONTROLS_COMBOBOX_NATIVE_COMBOBOX_WIN_H_ -#define UI_VIEWS_CONTROLS_COMBOBOX_NATIVE_COMBOBOX_WIN_H_ - -#include "ui/views/controls/combobox/native_combobox_wrapper.h" -#include "ui/views/controls/native_control_win.h" - -namespace views { - -class NativeComboboxWin : public NativeControlWin, - public NativeComboboxWrapper { - public: - explicit NativeComboboxWin(Combobox* combobox); - virtual ~NativeComboboxWin(); - - // Overridden from NativeComboboxWrapper: - virtual void UpdateFromModel() OVERRIDE; - virtual void UpdateSelectedIndex() OVERRIDE; - virtual void UpdateEnabled() OVERRIDE; - virtual int GetSelectedIndex() const OVERRIDE; - virtual bool IsDropdownOpen() const OVERRIDE; - virtual gfx::Size GetPreferredSize() OVERRIDE; - virtual View* GetView() OVERRIDE; - virtual void SetFocus() OVERRIDE; - virtual void ValidityStateChanged() OVERRIDE; - virtual bool HandleKeyPressed(const ui::KeyEvent& event) OVERRIDE; - virtual bool HandleKeyReleased(const ui::KeyEvent& event) OVERRIDE; - virtual void HandleFocus() OVERRIDE; - virtual void HandleBlur() OVERRIDE; - virtual gfx::NativeView GetTestingHandle() const OVERRIDE; - - protected: - // Overridden from NativeControlWin: - virtual bool ProcessMessage(UINT message, - WPARAM w_param, - LPARAM l_param, - LRESULT* result) OVERRIDE; - virtual void CreateNativeControl() OVERRIDE; - virtual void NativeControlCreated(HWND native_control) OVERRIDE; - - private: - void UpdateFont(); - - // The combobox we are bound to. - Combobox* combobox_; - - // The min width, in pixels, for the text content. - int content_width_; - - DISALLOW_COPY_AND_ASSIGN(NativeComboboxWin); -}; - -} // namespace views - -#endif // UI_VIEWS_CONTROLS_COMBOBOX_NATIVE_COMBOBOX_WIN_H_ diff --git a/chromium/ui/views/controls/combobox/native_combobox_wrapper.h b/chromium/ui/views/controls/combobox/native_combobox_wrapper.h deleted file mode 100644 index 539812fb472..00000000000 --- a/chromium/ui/views/controls/combobox/native_combobox_wrapper.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef UI_VIEWS_CONTROLS_COMBOBOX_NATIVE_COMBOBOX_WRAPPER_H_ -#define UI_VIEWS_CONTROLS_COMBOBOX_NATIVE_COMBOBOX_WRAPPER_H_ - -#include "ui/gfx/native_widget_types.h" -#include "ui/views/views_export.h" - -namespace gfx { -class Size; -} - -namespace ui { -class KeyEvent; -} - -namespace views { - -class Combobox; -class View; - -class VIEWS_EXPORT NativeComboboxWrapper { - public: - // Updates the combobox's content from its model. - virtual void UpdateFromModel() = 0; - - // Updates the selected index from the associated combobox. - virtual void UpdateSelectedIndex() = 0; - - // Updates the enabled state of the combobox from the associated view. - virtual void UpdateEnabled() = 0; - - // Returns the selected index. - virtual int GetSelectedIndex() const = 0; - - // Returns true if the combobox dropdown is open. - virtual bool IsDropdownOpen() const = 0; - - // Returns the preferred size of the combobox. - virtual gfx::Size GetPreferredSize() = 0; - - // Retrieves the view that hosts the native control. - virtual View* GetView() = 0; - - // Sets the focus to the button. - virtual void SetFocus() = 0; - - // Called when the combobox flipped validity. When invalid, it paints - // with white text on a red background. - virtual void ValidityStateChanged() = 0; - - // Invoked when a key is pressed/release on combobox. Subclasser should - // return true if the event has been processed and false otherwise. - // See also View::OnKeyPressed/OnKeyReleased. - virtual bool HandleKeyPressed(const ui::KeyEvent& e) = 0; - virtual bool HandleKeyReleased(const ui::KeyEvent& e) = 0; - - // Invoked when focus is being moved from or to the combobox. - // See also View::OnFocus/OnBlur. - virtual void HandleFocus() = 0; - virtual void HandleBlur() = 0; - - // Returns a handle to the underlying native view for testing. - virtual gfx::NativeView GetTestingHandle() const = 0; - - static NativeComboboxWrapper* CreateWrapper(Combobox* combobox); - - protected: - virtual ~NativeComboboxWrapper() {} -}; - -} // namespace views - -#endif // UI_VIEWS_CONTROLS_COMBOBOX_NATIVE_COMBOBOX_WRAPPER_H_ diff --git a/chromium/ui/views/controls/glow_hover_controller.cc b/chromium/ui/views/controls/glow_hover_controller.cc index f2e3bf26f30..f7fcd3fdd03 100644 --- a/chromium/ui/views/controls/glow_hover_controller.cc +++ b/chromium/ui/views/controls/glow_hover_controller.cc @@ -30,7 +30,7 @@ GlowHoverController::~GlowHoverController() { } void GlowHoverController::SetAnimationContainer( - ui::AnimationContainer* container) { + gfx::AnimationContainer* container) { animation_.SetContainer(container); } @@ -45,7 +45,7 @@ void GlowHoverController::Show(Style style) { case SUBTLE: opacity_scale_ = kTrackOpacityScale; animation_.SetSlideDuration(kTrackHoverDurationMs); - animation_.SetTweenType(ui::Tween::EASE_OUT); + animation_.SetTweenType(gfx::Tween::EASE_OUT); animation_.Show(); break; case PRONOUNCED: @@ -58,7 +58,7 @@ void GlowHoverController::Show(Style style) { } void GlowHoverController::Hide() { - animation_.SetTweenType(ui::Tween::EASE_IN); + animation_.SetTweenType(gfx::Tween::EASE_IN); animation_.Hide(); } @@ -117,11 +117,11 @@ void GlowHoverController::Draw(gfx::Canvas* canvas, (view_->height() - mask_image.height()) / 2); } -void GlowHoverController::AnimationEnded(const ui::Animation* animation) { +void GlowHoverController::AnimationEnded(const gfx::Animation* animation) { view_->SchedulePaint(); } -void GlowHoverController::AnimationProgressed(const ui::Animation* animation) { +void GlowHoverController::AnimationProgressed(const gfx::Animation* animation) { view_->SchedulePaint(); } diff --git a/chromium/ui/views/controls/glow_hover_controller.h b/chromium/ui/views/controls/glow_hover_controller.h index 7d8e62ce2bd..2ac423e42d5 100644 --- a/chromium/ui/views/controls/glow_hover_controller.h +++ b/chromium/ui/views/controls/glow_hover_controller.h @@ -5,8 +5,8 @@ #ifndef UI_VIEWS_CONTROLS_GLOW_HOVER_CONTROLLER_H_ #define UI_VIEWS_CONTROLS_GLOW_HOVER_CONTROLLER_H_ -#include "ui/base/animation/animation_delegate.h" -#include "ui/base/animation/slide_animation.h" +#include "ui/gfx/animation/animation_delegate.h" +#include "ui/gfx/animation/slide_animation.h" #include "ui/views/views_export.h" namespace gfx { @@ -27,7 +27,7 @@ class View; // OnPaint() -> if ShouldDraw() returns true invoke Draw(). // Internally GlowHoverController uses an animation to animate the glow and // invokes SchedulePaint() back on the View as necessary. -class VIEWS_EXPORT GlowHoverController : public ui::AnimationDelegate { +class VIEWS_EXPORT GlowHoverController : public gfx::AnimationDelegate { public: enum Style { SUBTLE, @@ -38,7 +38,7 @@ class VIEWS_EXPORT GlowHoverController : public ui::AnimationDelegate { virtual ~GlowHoverController(); // Sets the AnimationContainer used by the animation. - void SetAnimationContainer(ui::AnimationContainer* container); + void SetAnimationContainer(gfx::AnimationContainer* container); // Sets the location of the hover, relative to the View passed to the // constructor. @@ -64,16 +64,16 @@ class VIEWS_EXPORT GlowHoverController : public ui::AnimationDelegate { // |mask_image| is used to determine what parts of the canvas to draw on. void Draw(gfx::Canvas* canvas, const gfx::ImageSkia& mask_image) const; - // ui::AnimationDelegate overrides: - virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE; - virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; + // gfx::AnimationDelegate overrides: + virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE; + virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; private: // View we're drawing to. views::View* view_; // Opacity of the glow ramps up over time. - ui::SlideAnimation animation_; + gfx::SlideAnimation animation_; // Location of the glow, relative to view. gfx::Point location_; diff --git a/chromium/ui/views/controls/label.cc b/chromium/ui/views/controls/label.cc index 3e81ce5451c..7d4bc7e8470 100644 --- a/chromium/ui/views/controls/label.cc +++ b/chromium/ui/views/controls/label.cc @@ -16,12 +16,12 @@ #include "base/strings/utf_string_conversions.h" #include "ui/base/accessibility/accessible_view_state.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/base/text/text_elider.h" #include "ui/gfx/canvas.h" #include "ui/gfx/color_utils.h" -#include "ui/gfx/font.h" #include "ui/gfx/insets.h" #include "ui/gfx/shadow_value.h" +#include "ui/gfx/text_elider.h" +#include "ui/gfx/text_utils.h" #include "ui/native_theme/native_theme.h" #include "ui/views/background.h" @@ -31,6 +31,11 @@ namespace { const int kFocusBorderPadding = 1; const int kCachedSizeLimit = 10; +gfx::FontList GetDefaultFontList() { + return ui::ResourceBundle::GetSharedInstance().GetFontList( + ui::ResourceBundle::BaseFont); +} + } // namespace namespace views { @@ -39,27 +44,39 @@ namespace views { const char Label::kViewClassName[] = "Label"; Label::Label() { - Init(string16(), GetDefaultFont()); + Init(string16(), GetDefaultFontList()); } Label::Label(const string16& text) { - Init(text, GetDefaultFont()); + Init(text, GetDefaultFontList()); +} + +Label::Label(const string16& text, const gfx::FontList& font_list) { + Init(text, font_list); } Label::Label(const string16& text, const gfx::Font& font) { - Init(text, font); + Init(text, gfx::FontList(font)); } Label::~Label() { } -void Label::SetFont(const gfx::Font& font) { - font_ = font; +void Label::SetFontList(const gfx::FontList& font_list) { + font_list_ = font_list; ResetCachedSize(); PreferredSizeChanged(); SchedulePaint(); } +const gfx::Font& Label::font() const { + return font_list_.GetPrimaryFont(); +} + +void Label::SetFont(const gfx::Font& font) { + SetFontList(gfx::FontList(font)); +} + void Label::SetText(const string16& text) { if (text == text_) return; @@ -172,7 +189,7 @@ void Label::SizeToFit(int max_width) { int label_width = 0; for (std::vector<string16>::const_iterator iter = lines.begin(); iter != lines.end(); ++iter) { - label_width = std::max(label_width, font_.GetStringWidth(*iter)); + label_width = std::max(label_width, gfx::GetStringWidth(*iter, font_list_)); } label_width += GetInsets().width(); @@ -202,7 +219,7 @@ gfx::Insets Label::GetInsets() const { } int Label::GetBaseline() const { - return GetInsets().top() + font_.GetBaseline(); + return GetInsets().top() + font_list_.GetBaseline(); } gfx::Size Label::GetPreferredSize() { @@ -234,9 +251,9 @@ int Label::GetHeightForWidth(int w) { int cache_width = w; - int h = font_.GetHeight(); + int h = font_list_.GetHeight(); const int flags = ComputeDrawStringFlags(); - gfx::Canvas::SizeStringInt(text_, font_, &w, &h, line_height_, flags); + gfx::Canvas::SizeStringInt(text_, font_list_, &w, &h, line_height_, flags); cached_heights_[cached_heights_cursor_] = gfx::Size(cache_width, h); cached_heights_cursor_ = (cached_heights_cursor_ + 1) % kCachedSizeLimit; return h + GetInsets().height(); @@ -297,7 +314,7 @@ void Label::PaintText(gfx::Canvas* canvas, if (has_shadow_) shadows.push_back(gfx::ShadowValue(shadow_offset_, 0, enabled() ? enabled_shadow_color_ : disabled_shadow_color_)); - canvas->DrawStringWithShadows(text, font_, + canvas->DrawStringRectWithShadows(text, font_list_, enabled() ? actual_enabled_color_ : actual_disabled_color_, text_bounds, line_height_, flags, shadows); @@ -316,13 +333,13 @@ gfx::Size Label::GetTextSize() const { // on Linux. int w = is_multi_line_ ? GetAvailableRect().width() : std::numeric_limits<int>::max(); - int h = font_.GetHeight(); + int h = font_list_.GetHeight(); // For single-line strings, ignore the available width and calculate how // wide the text wants to be. int flags = ComputeDrawStringFlags(); if (!is_multi_line_) flags |= gfx::Canvas::NO_ELLIPSIS; - gfx::Canvas::SizeStringInt(text_, font_, &w, &h, line_height_, flags); + gfx::Canvas::SizeStringInt(text_, font_list_, &w, &h, line_height_, flags); text_size_.SetSize(w, h); text_size_valid_ = true; } @@ -352,13 +369,8 @@ void Label::OnNativeThemeChanged(const ui::NativeTheme* theme) { UpdateColorsFromTheme(theme); } -// static -gfx::Font Label::GetDefaultFont() { - return ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont); -} - -void Label::Init(const string16& text, const gfx::Font& font) { - font_ = font; +void Label::Init(const string16& text, const gfx::FontList& font_list) { + font_list_ = font_list; enabled_color_set_ = disabled_color_set_ = background_color_set_ = false; auto_color_readability_ = true; UpdateColorsFromTheme(ui::NativeTheme::instance()); @@ -483,14 +495,15 @@ void Label::CalculateDrawStringParams(string16* paint_text, if (is_multi_line_ || (elide_behavior_ == NO_ELIDE)) { *paint_text = text_; } else if (elide_behavior_ == ELIDE_IN_MIDDLE) { - *paint_text = ui::ElideText(text_, font_, GetAvailableRect().width(), - ui::ELIDE_IN_MIDDLE); + *paint_text = gfx::ElideText(text_, font_list_, GetAvailableRect().width(), + gfx::ELIDE_IN_MIDDLE); } else if (elide_behavior_ == ELIDE_AT_END) { - *paint_text = ui::ElideText(text_, font_, GetAvailableRect().width(), - ui::ELIDE_AT_END); + *paint_text = gfx::ElideText(text_, font_list_, GetAvailableRect().width(), + gfx::ELIDE_AT_END); } else { DCHECK_EQ(ELIDE_AS_EMAIL, elide_behavior_); - *paint_text = ui::ElideEmail(text_, font_, GetAvailableRect().width()); + *paint_text = gfx::ElideEmail(text_, font_list_, + GetAvailableRect().width()); } *text_bounds = GetTextBounds(); @@ -524,7 +537,7 @@ void Label::ResetCachedSize() { bool Label::ShouldShowDefaultTooltip() const { return !is_multi_line_ && - font_.GetStringWidth(text_) > GetAvailableRect().width(); + gfx::GetStringWidth(text_, font_list_) > GetAvailableRect().width(); } } // namespace views diff --git a/chromium/ui/views/controls/label.h b/chromium/ui/views/controls/label.h index d637d7fb39e..40534ff654f 100644 --- a/chromium/ui/views/controls/label.h +++ b/chromium/ui/views/controls/label.h @@ -12,7 +12,7 @@ #include "base/gtest_prod_util.h" #include "base/strings/string16.h" #include "third_party/skia/include/core/SkColor.h" -#include "ui/gfx/font.h" +#include "ui/gfx/font_list.h" #include "ui/gfx/text_constants.h" #include "ui/views/view.h" @@ -54,12 +54,16 @@ class VIEWS_EXPORT Label : public View { Label(); explicit Label(const string16& text); - Label(const string16& text, const gfx::Font& font); + Label(const string16& text, const gfx::FontList& font_list); + Label(const string16& text, const gfx::Font& font); // OBSOLETE virtual ~Label(); - // Get or set the font used by this label. - const gfx::Font& font() const { return font_; } - virtual void SetFont(const gfx::Font& font); + // Gets or sets the fonts used by this label. + const gfx::FontList& font_list() const { return font_list_; } + virtual void SetFontList(const gfx::FontList& font_list); + // Obsolete gfx::Font version. Should use gfx::FontList version instead. + const gfx::Font& font() const; // OBSOLETE + virtual void SetFont(const gfx::Font& font); // OBSOLETE // Get or set the label text. const string16& text() const { return text_; } @@ -119,7 +123,7 @@ class VIEWS_EXPORT Label : public View { // Get or set the distance in pixels between baselines of multi-line text. // Default is 0, indicating the distance between lines should be the standard - // one for the label's text, font, and platform. + // one for the label's text, font list, and platform. int line_height() const { return line_height_; } void SetLineHeight(int height); @@ -208,9 +212,7 @@ class VIEWS_EXPORT Label : public View { // Calls ComputeDrawStringFlags(). FRIEND_TEST_ALL_PREFIXES(LabelTest, DisableSubpixelRendering); - static gfx::Font GetDefaultFont(); - - void Init(const string16& text, const gfx::Font& font); + void Init(const string16& text, const gfx::FontList& font_list); void RecalculateColors(); @@ -236,7 +238,7 @@ class VIEWS_EXPORT Label : public View { bool ShouldShowDefaultTooltip() const; string16 text_; - gfx::Font font_; + gfx::FontList font_list_; SkColor requested_enabled_color_; SkColor actual_enabled_color_; SkColor requested_disabled_color_; diff --git a/chromium/ui/views/controls/label_unittest.cc b/chromium/ui/views/controls/label_unittest.cc index 134a05d7ee0..be752810f3b 100644 --- a/chromium/ui/views/controls/label_unittest.cc +++ b/chromium/ui/views/controls/label_unittest.cc @@ -16,17 +16,13 @@ namespace views { // All text sizing measurements (width and height) should be greater than this. const int kMinTextDimension = 4; -TEST(LabelTest, FontPropertyCourier) { +TEST(LabelTest, FontPropertySymbol) { Label label; - std::string font_name("courier"); - // Note: This test is size dependent since Courier does not support all sizes. + std::string font_name("symbol"); gfx::Font font(font_name, 26); - label.SetFont(font); - gfx::Font font_used = label.font(); -#if defined(OS_WIN) - // On Linux, this results in "Sans" instead of "courier". + label.SetFontList(gfx::FontList(font)); + gfx::Font font_used = label.font_list().GetPrimaryFont(); EXPECT_EQ(font_name, font_used.GetFontName()); -#endif EXPECT_EQ(26, font_used.GetFontSize()); } @@ -34,8 +30,8 @@ TEST(LabelTest, FontPropertyArial) { Label label; std::string font_name("arial"); gfx::Font font(font_name, 30); - label.SetFont(font); - gfx::Font font_used = label.font(); + label.SetFontList(gfx::FontList(font)); + gfx::Font font_used = label.font_list().GetPrimaryFont(); EXPECT_EQ(font_name, font_used.GetFontName()); EXPECT_EQ(30, font_used.GetFontSize()); } diff --git a/chromium/ui/views/controls/link.cc b/chromium/ui/views/controls/link.cc index b82cd51533f..b2bcc8f692b 100644 --- a/chromium/ui/views/controls/link.cc +++ b/chromium/ui/views/controls/link.cc @@ -9,8 +9,8 @@ #include "base/logging.h" #include "base/strings/utf_string_conversions.h" #include "ui/base/accessibility/accessible_view_state.h" -#include "ui/base/events/event.h" -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/color_utils.h" #include "ui/gfx/font.h" #include "ui/views/controls/link_listener.h" diff --git a/chromium/ui/views/controls/menu/menu_config.cc b/chromium/ui/views/controls/menu/menu_config.cc index 16570855e30..1c34ac0b3e0 100644 --- a/chromium/ui/views/controls/menu/menu_config.cc +++ b/chromium/ui/views/controls/menu/menu_config.cc @@ -13,13 +13,13 @@ namespace views { MenuConfig::MenuConfig(const ui::NativeTheme* theme) : text_color(SK_ColorBLACK), arrow_color(SK_ColorBLACK), - menu_vertical_border_size(7), + menu_vertical_border_size(3), menu_horizontal_border_size(0), submenu_horizontal_inset(3), - item_top_margin(7), - item_bottom_margin(6), - item_no_icon_top_margin(7), - item_no_icon_bottom_margin(7), + item_top_margin(4), + item_bottom_margin(3), + item_no_icon_top_margin(4), + item_no_icon_bottom_margin(4), item_left_margin(10), label_to_arrow_padding(10), arrow_to_edge_padding(5), @@ -32,7 +32,7 @@ MenuConfig::MenuConfig(const ui::NativeTheme* theme) arrow_height(9), arrow_width(9), gutter_width(0), - separator_height(15), + separator_height(11), separator_upper_height(3), separator_lower_height(4), separator_spacing_height(3), @@ -48,7 +48,6 @@ MenuConfig::MenuConfig(const ui::NativeTheme* theme) native_theme(theme), show_delay(400), corner_radius(0) { - AdjustForMenuVariations(); // Use 40px tall menu items when running in touch optimized mode. // For Windows use 40px tall menu items when running in touch optimized mode. if (ui::GetDisplayLayout() == ui::LAYOUT_TOUCH) { @@ -60,28 +59,4 @@ MenuConfig::MenuConfig(const ui::NativeTheme* theme) MenuConfig::~MenuConfig() {} -void MenuConfig::AdjustForMenuVariations() { - switch (ui::NativeTheme::GetMenuVariation()) { - case ui::NativeTheme::MENU_VARIATION_COMPACT_1: - case ui::NativeTheme::MENU_VARIATION_CONTRAST: - item_top_margin = 5; - item_bottom_margin = 4; - item_no_icon_top_margin = 5; - item_no_icon_bottom_margin = 5; - separator_height = 11; - menu_vertical_border_size = 5; - break; - case ui::NativeTheme::MENU_VARIATION_COMPACT_2: - item_top_margin = 4; - item_bottom_margin = 3; - item_no_icon_top_margin = 4; - item_no_icon_bottom_margin = 4; - separator_height = 11; - menu_vertical_border_size = 3; - break; - default: - break; - } -} - } // namespace views diff --git a/chromium/ui/views/controls/menu/menu_config.h b/chromium/ui/views/controls/menu/menu_config.h index ac947823321..96eb21ac219 100644 --- a/chromium/ui/views/controls/menu/menu_config.h +++ b/chromium/ui/views/controls/menu/menu_config.h @@ -139,9 +139,6 @@ struct VIEWS_EXPORT MenuConfig { #if defined(USE_AURA) void InitAura(const ui::NativeTheme* theme); #endif - - // Adjust some menu values for different menu variations. - void AdjustForMenuVariations(); }; } // namespace views diff --git a/chromium/ui/views/controls/menu/menu_controller.cc b/chromium/ui/views/controls/menu/menu_controller.cc index 960130da9ad..fe203dd0e98 100644 --- a/chromium/ui/views/controls/menu/menu_controller.cc +++ b/chromium/ui/views/controls/menu/menu_controller.cc @@ -15,19 +15,25 @@ #include "base/time/time.h" #include "ui/base/dragdrop/drag_utils.h" #include "ui/base/dragdrop/os_exchange_data.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/events/event_utils.h" -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/events/event_constants.h" +#include "ui/events/event_utils.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/native_widget_types.h" #include "ui/gfx/screen.h" +#include "ui/gfx/vector2d.h" #include "ui/native_theme/native_theme.h" #include "ui/views/controls/button/menu_button.h" #include "ui/views/controls/menu/menu_config.h" #include "ui/views/controls/menu/menu_controller_delegate.h" +#include "ui/views/controls/menu/menu_host_root_view.h" #include "ui/views/controls/menu/menu_scroll_view_container.h" #include "ui/views/controls/menu/submenu_view.h" #include "ui/views/drag_utils.h" +#include "ui/views/event_utils.h" +#include "ui/views/focus/view_storage.h" +#include "ui/views/mouse_constants.h" #include "ui/views/view_constants.h" #include "ui/views/views_delegate.h" #include "ui/views/widget/root_view.h" @@ -36,7 +42,6 @@ #if defined(USE_AURA) #include "ui/aura/env.h" #include "ui/aura/root_window.h" -#include "ui/aura/window.h" #endif #if defined(OS_WIN) @@ -68,12 +73,17 @@ namespace { // When showing context menu on mouse down, the user might accidentally select // the menu item on the subsequent mouse up. To prevent this, we add the // following delay before the user is able to select an item. -static int context_menu_selection_hold_time_ms = 200; +static int menu_selection_hold_time_ms = kMinimumMsPressedToActivate; // The spacing offset for the bubble tip. const int kBubbleTipSizeLeftRight = 12; const int kBubbleTipSizeTopBottom = 11; +// The maximum distance (in DIPS) that the mouse can be moved before it should +// trigger a mouse menu item activation (regardless of how long the menu has +// been showing). +const float kMaximumLengthMovedToActivate = 4.0f; + // Returns true if the mnemonic of |menu| matches key. bool MatchesMnemonic(MenuItemView* menu, char16 key) { return menu->GetMnemonic() == key; @@ -268,7 +278,7 @@ struct MenuController::SelectByCharDetails { MenuController::State::State() : item(NULL), submenu_open(false), - anchor(views::MenuItemView::TOPLEFT), + anchor(MenuItemView::TOPLEFT), context_menu(false) {} MenuController::State::~State() {} @@ -295,12 +305,26 @@ MenuItemView* MenuController::Run(Widget* parent, drag_in_progress_ = false; closing_event_time_ = base::TimeDelta(); menu_start_time_ = base::TimeTicks::Now(); + menu_start_mouse_press_loc_ = gfx::Point(); // If we are shown on mouse press, we will eat the subsequent mouse down and // the parent widget will not be able to reset its state (it might have mouse // capture from the mouse down). So we clear its state here. - if (parent && parent->GetRootView()) - parent->GetRootView()->SetMouseHandler(NULL); + if (parent) { + View* root_view = parent->GetRootView(); + if (root_view) { + root_view->SetMouseHandler(NULL); + const ui::Event* event = + static_cast<internal::RootView*>(root_view)->current_event(); + if (event && event->type() == ui::ET_MOUSE_PRESSED) { + gfx::Point screen_loc( + static_cast<const ui::MouseEvent*>(event)->location()); + View::ConvertPointToScreen( + static_cast<View*>(event->target()), &screen_loc); + menu_start_mouse_press_loc_ = screen_loc; + } + } + } bool nested_menu = showing_; if (showing_) { @@ -485,9 +509,9 @@ void MenuController::OnMouseReleased(SubmenuView* source, // If it is from an empty menu, use parent context menu instead of that. if (menu == NULL && part.submenu->child_count() == 1 && - part.submenu->child_at(0)->id() - == views::MenuItemView::kEmptyMenuItemViewID) + part.submenu->child_at(0)->id() == MenuItemView::kEmptyMenuItemViewID) { menu = part.parent; + } if (menu != NULL && ShowContextMenu(menu, source, event, ui::MENU_SOURCE_MOUSE)) @@ -500,10 +524,23 @@ void MenuController::OnMouseReleased(SubmenuView* source, if (!part.is_scroll() && part.menu && !(part.menu->HasSubmenu() && (event.flags() & ui::EF_LEFT_MOUSE_BUTTON))) { - if (active_mouse_view_) { + if (GetActiveMouseView()) { SendMouseReleaseToActiveView(source, event); return; } + // If a mouse release was received quickly after showing. + base::TimeDelta time_shown = base::TimeTicks::Now() - menu_start_time_; + if (time_shown.InMilliseconds() < menu_selection_hold_time_ms) { + // And it wasn't far from the mouse press location. + gfx::Point screen_loc(event.location()); + View::ConvertPointToScreen(source->GetScrollViewContainer(), &screen_loc); + gfx::Vector2d moved = screen_loc - menu_start_mouse_press_loc_; + if (moved.Length() < kMaximumLengthMovedToActivate) { + // Ignore the mouse release as it was likely this menu was shown under + // the mouse and the action was just a normal click. + return; + } + } if (part.menu->GetDelegate()->ShouldExecuteCommandWithoutClosingMenu( part.menu->GetCommand(), event)) { part.menu->GetDelegate()->ExecuteCommand(part.menu->GetCommand(), @@ -512,11 +549,11 @@ void MenuController::OnMouseReleased(SubmenuView* source, } if (!part.menu->NonIconChildViewsCount() && part.menu->GetDelegate()->IsTriggerableEvent(part.menu, event)) { - int64 time_since_menu_start = - (base::TimeTicks::Now() - menu_start_time_).InMilliseconds(); + base::TimeDelta shown_time = base::TimeTicks::Now() - menu_start_time_; if (!state_.context_menu || !View::ShouldShowContextMenuOnMousePress() || - time_since_menu_start > context_menu_selection_hold_time_ms) + shown_time.InMilliseconds() > menu_selection_hold_time_ms) { Accept(part.menu, event.flags()); + } return; } } else if (part.type == MenuPart::MENU_ITEM) { @@ -740,7 +777,7 @@ void MenuController::UpdateSubmenuSelection(SubmenuView* submenu) { gfx::Point point = GetScreen()->GetCursorScreenPoint(); const SubmenuView* root_submenu = submenu->GetMenuItem()->GetRootMenuItem()->GetSubmenu(); - views::View::ConvertPointFromScreen( + View::ConvertPointFromScreen( root_submenu->GetWidget()->GetRootView(), &point); HandleMouseLocation(submenu, point); } @@ -753,8 +790,8 @@ void MenuController::OnWidgetDestroying(Widget* widget) { } // static -void MenuController::TurnOffContextMenuSelectionHoldForTest() { - context_menu_selection_hold_time_ms = -1; +void MenuController::TurnOffMenuSelectionHoldForTest() { + menu_selection_hold_time_ms = -1; } void MenuController::SetSelection(MenuItemView* menu_item, @@ -828,7 +865,7 @@ void MenuController::SetSelectionOnPointerDown(SubmenuView* source, if (!blocking_run_) return; - DCHECK(!active_mouse_view_); + DCHECK(!GetActiveMouseView()); MenuPart part = GetMenuPart(source, event.location()); if (part.is_scroll()) @@ -855,9 +892,15 @@ void MenuController::SetSelectionOnPointerDown(SubmenuView* source, #if defined(OS_WIN) // We're going to close and we own the mouse capture. We need to repost the - // mouse down, otherwise the window the user clicked on won't get the - // event. - RepostEvent(source, event); + // mouse down, otherwise the window the user clicked on won't get the event. + if (!state_.item) { + // We some times get an event after closing all the menus. Ignore it. Make + // sure the menu is in fact not visible. If the menu is visible, then + // we're in a bad state where we think the menu isn't visibile but it is. + DCHECK(!source->GetWidget()->IsVisible()); + } else { + RepostEvent(source, event); + } #endif // And close. @@ -914,7 +957,7 @@ void MenuController::StartDrag(SubmenuView* source, View::ConvertPointToTarget(NULL, item, &press_loc); gfx::Point widget_loc(press_loc); View::ConvertPointToWidget(item, &widget_loc); - scoped_ptr<gfx::Canvas> canvas(views::GetCanvasForDragImage( + scoped_ptr<gfx::Canvas> canvas(GetCanvasForDragImage( source->GetWidget(), gfx::Size(item->width(), item->height()))); item->PaintButton(canvas.get(), MenuItemView::PB_FOR_DRAG); @@ -1119,7 +1162,7 @@ MenuController::MenuController(ui::NativeTheme* theme, last_drop_operation_(MenuDelegate::DROP_UNKNOWN), showing_submenu_(false), menu_button_(NULL), - active_mouse_view_(NULL), + active_mouse_view_id_(ViewStorage::GetInstance()->CreateStorageID()), delegate_(delegate), message_loop_depth_(0), menu_config_(theme), @@ -1218,8 +1261,7 @@ bool MenuController::ShowSiblingMenu(SubmenuView* source, return false; } - gfx::NativeWindow window_under_mouse = - GetScreen()->GetWindowAtCursorScreenPoint(); + gfx::NativeWindow window_under_mouse = GetScreen()->GetWindowUnderCursor(); // TODO(oshima): Replace with views only API. if (!owner_ || window_under_mouse != owner_->GetNativeWindow()) return false; @@ -1541,7 +1583,7 @@ void MenuController::OpenMenuImpl(MenuItemView* item, bool show) { void MenuController::MenuChildrenChanged(MenuItemView* item) { DCHECK(item); // Menu shouldn't be updated during drag operation. - DCHECK(!active_mouse_view_); + DCHECK(!GetActiveMouseView()); // If the current item or pending item is a descendant of the item // that changed, move the selection back to the changed item. @@ -2058,85 +2100,53 @@ bool MenuController::SelectByChar(char16 character) { return false; } -#if defined(OS_WIN) void MenuController::RepostEvent(SubmenuView* source, const ui::LocatedEvent& event) { - if (!state_.item) { - // We some times get an event after closing all the menus. Ignore it. - // Make sure the menu is in fact not visible. If the menu is visible, then - // we're in a bad state where we think the menu isn't visibile but it is. - DCHECK(!source->GetWidget()->IsVisible()); - return; - } - gfx::Point screen_loc(event.location()); View::ConvertPointToScreen(source->GetScrollViewContainer(), &screen_loc); - HWND window = WindowFromPoint(screen_loc.ToPOINT()); - if (window) { - // Release the capture. - SubmenuView* submenu = state_.item->GetRootMenuItem()->GetSubmenu(); - submenu->ReleaseCapture(); - - if (submenu->GetWidget()->GetNativeView() && - GetWindowThreadProcessId( - views::HWNDForNativeView(submenu->GetWidget()->GetNativeView()), - NULL) != GetWindowThreadProcessId(window, NULL)) { - // Even though we have mouse capture, windows generates a mouse event - // if the other window is in a separate thread. Don't generate an event in - // this case else the target window can get double events leading to bad - // behavior. - return; - } - // Convert the coordinates to the target window. - RECT window_bounds; - GetWindowRect(window, &window_bounds); - int window_x = screen_loc.x() - window_bounds.left; - int window_y = screen_loc.y() - window_bounds.top; - - // Determine whether the click was in the client area or not. - // NOTE: WM_NCHITTEST coordinates are relative to the screen. - LRESULT nc_hit_result = SendMessage(window, WM_NCHITTEST, 0, - MAKELPARAM(screen_loc.x(), - screen_loc.y())); - const bool in_client_area = (nc_hit_result == HTCLIENT); - - // TODO(sky): this isn't right. The event to generate should correspond - // with the event we just got. MouseEvent only tells us what is down, - // which may differ. Need to add ability to get changed button from - // MouseEvent. - int event_type; - int flags = event.flags(); - if (flags & ui::EF_LEFT_MOUSE_BUTTON) - event_type = in_client_area ? WM_LBUTTONDOWN : WM_NCLBUTTONDOWN; - else if (flags & ui::EF_MIDDLE_MOUSE_BUTTON) - event_type = in_client_area ? WM_MBUTTONDOWN : WM_NCMBUTTONDOWN; - else if (flags & ui::EF_RIGHT_MOUSE_BUTTON) - event_type = in_client_area ? WM_RBUTTONDOWN : WM_NCRBUTTONDOWN; - else - event_type = 0; // Unknown mouse press. + gfx::NativeView native_view = source->GetWidget()->GetNativeView(); + gfx::Screen* screen = gfx::Screen::GetScreenFor(native_view); + gfx::NativeWindow window = screen->GetWindowAtScreenPoint(screen_loc); - if (event_type) { - if (in_client_area) { - PostMessage(window, event_type, event.native_event().wParam, - MAKELPARAM(window_x, window_y)); - } else { - PostMessage(window, event_type, nc_hit_result, - MAKELPARAM(screen_loc.x(), screen_loc.y())); - } + if (!window) + return; + +#if defined(OS_WIN) + // Release the capture. + SubmenuView* submenu = state_.item->GetRootMenuItem()->GetSubmenu(); + submenu->ReleaseCapture(); + + gfx::NativeView view = submenu->GetWidget()->GetNativeView(); + if (view) { + DWORD view_tid = GetWindowThreadProcessId(HWNDForNativeView(view), NULL); + if (view_tid != GetWindowThreadProcessId(HWNDForNativeView(window), NULL)) { + // Even though we have mouse capture, windows generates a mouse event if + // the other window is in a separate thread. Only repost an event if + // |view| was created on the same thread, else the target window can get + // double events leading to bad behavior. + return; } } -} -#elif defined(USE_AURA) -void MenuController::RepostEvent(SubmenuView* source, - const ui::LocatedEvent& event) { - aura::RootWindow* root_window = - source->GetWidget()->GetNativeWindow()->GetRootWindow(); - DCHECK(root_window); - root_window->RepostEvent(event); -} #endif + scoped_ptr<ui::LocatedEvent> clone; + if (event.IsMouseEvent()) { + clone.reset(new ui::MouseEvent(static_cast<const ui::MouseEvent&>(event))); + } else if (event.IsGestureEvent()) { + // TODO(rbyers): Gesture event repost is tricky to get right + // crbug.com/170987. + return; + } else { + NOTREACHED(); + return; + } + clone->set_location(screen_loc); + + RepostLocatedEvent(window, *clone); +} + + void MenuController::SetDropMenuItem( MenuItemView* new_target, MenuDelegate::DropPosition new_position) { @@ -2185,63 +2195,75 @@ void MenuController::UpdateActiveMouseView(SubmenuView* event_source, if (target == target_menu || !target->enabled()) target = NULL; } - if (target != active_mouse_view_) { + View* active_mouse_view = GetActiveMouseView(); + if (target != active_mouse_view) { SendMouseCaptureLostToActiveView(); - active_mouse_view_ = target; - if (active_mouse_view_) { + active_mouse_view = target; + SetActiveMouseView(active_mouse_view); + if (active_mouse_view) { gfx::Point target_point(target_menu_loc); View::ConvertPointToTarget( - target_menu, active_mouse_view_, &target_point); + target_menu, active_mouse_view, &target_point); ui::MouseEvent mouse_entered_event(ui::ET_MOUSE_ENTERED, target_point, target_point, 0); - active_mouse_view_->OnMouseEntered(mouse_entered_event); + active_mouse_view->OnMouseEntered(mouse_entered_event); ui::MouseEvent mouse_pressed_event(ui::ET_MOUSE_PRESSED, target_point, target_point, event.flags()); - active_mouse_view_->OnMousePressed(mouse_pressed_event); + active_mouse_view->OnMousePressed(mouse_pressed_event); } } - if (active_mouse_view_) { + if (active_mouse_view) { gfx::Point target_point(target_menu_loc); - View::ConvertPointToTarget(target_menu, active_mouse_view_, &target_point); + View::ConvertPointToTarget(target_menu, active_mouse_view, &target_point); ui::MouseEvent mouse_dragged_event(ui::ET_MOUSE_DRAGGED, target_point, target_point, event.flags()); - active_mouse_view_->OnMouseDragged(mouse_dragged_event); + active_mouse_view->OnMouseDragged(mouse_dragged_event); } } void MenuController::SendMouseReleaseToActiveView(SubmenuView* event_source, const ui::MouseEvent& event) { - if (!active_mouse_view_) + View* active_mouse_view = GetActiveMouseView(); + if (!active_mouse_view) return; gfx::Point target_loc(event.location()); View::ConvertPointToScreen(event_source->GetScrollViewContainer(), &target_loc); - View::ConvertPointToTarget(NULL, active_mouse_view_, &target_loc); - ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, - target_loc, target_loc, - event.flags()); - // Reset the active_mouse_view_ before sending mouse released. That way if it - // calls back to us, we aren't in a weird state. - View* active_view = active_mouse_view_; - active_mouse_view_ = NULL; - active_view->OnMouseReleased(release_event); + View::ConvertPointToTarget(NULL, active_mouse_view, &target_loc); + ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, target_loc, target_loc, + event.flags()); + // Reset active mouse view before sending mouse released. That way if it calls + // back to us, we aren't in a weird state. + SetActiveMouseView(NULL); + active_mouse_view->OnMouseReleased(release_event); } void MenuController::SendMouseCaptureLostToActiveView() { - if (!active_mouse_view_) + View* active_mouse_view = GetActiveMouseView(); + if (!active_mouse_view) return; // Reset the active_mouse_view_ before sending mouse capture lost. That way if // it calls back to us, we aren't in a weird state. - View* active_view = active_mouse_view_; - active_mouse_view_ = NULL; - active_view->OnMouseCaptureLost(); + SetActiveMouseView(NULL); + active_mouse_view->OnMouseCaptureLost(); +} + +void MenuController::SetActiveMouseView(View* view) { + if (view) + ViewStorage::GetInstance()->StoreView(active_mouse_view_id_, view); + else + ViewStorage::GetInstance()->RemoveView(active_mouse_view_id_); +} + +View* MenuController::GetActiveMouseView() { + return ViewStorage::GetInstance()->RetrieveView(active_mouse_view_id_); } void MenuController::SetExitType(ExitType type) { diff --git a/chromium/ui/views/controls/menu/menu_controller.h b/chromium/ui/views/controls/menu/menu_controller.h index 6dfdd528e9f..1bd571aa043 100644 --- a/chromium/ui/views/controls/menu/menu_controller.h +++ b/chromium/ui/views/controls/menu/menu_controller.h @@ -15,7 +15,7 @@ #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "base/timer/timer.h" -#include "ui/base/events/event_constants.h" +#include "ui/events/event_constants.h" #include "ui/views/controls/menu/menu_delegate.h" #include "ui/views/controls/menu/menu_item_view.h" #include "ui/views/widget/widget_observer.h" @@ -137,7 +137,7 @@ class VIEWS_EXPORT MenuController : public base::MessageLoop::Dispatcher, virtual void OnWidgetDestroying(Widget* widget) OVERRIDE; // Only used for testing. - static void TurnOffContextMenuSelectionHoldForTest(); + static void TurnOffMenuSelectionHoldForTest(); private: friend class internal::MenuRunnerImpl; @@ -445,7 +445,7 @@ class VIEWS_EXPORT MenuController : public base::MessageLoop::Dispatcher, // Stops scrolling. void StopScrolling(); - // Updates |active_mouse_view_| from the location of the event and sends it + // Updates active mouse view from the location of the event and sends it // the appropriate events. This is used to send mouse events to child views so // that they react to click-drag-release as if the user clicked on the view // itself. @@ -453,15 +453,19 @@ class VIEWS_EXPORT MenuController : public base::MessageLoop::Dispatcher, const ui::MouseEvent& event, View* target_menu); - // Sends a mouse release event to the current |active_mouse_view_| and sets + // Sends a mouse release event to the current active mouse view and sets // it to null. void SendMouseReleaseToActiveView(SubmenuView* event_source, const ui::MouseEvent& event); - // Sends a mouse capture lost event to the current |active_mouse_view_| and - // sets it to null. + // Sends a mouse capture lost event to the current active mouse view and sets + // it to null. void SendMouseCaptureLostToActiveView(); + // Sets/gets the active mouse view. See UpdateActiveMouseView() for details. + void SetActiveMouseView(View* view); + View* GetActiveMouseView(); + // Sets exit type. void SetExitType(ExitType type); @@ -556,9 +560,9 @@ class VIEWS_EXPORT MenuController : public base::MessageLoop::Dispatcher, MenuButton* menu_button_; - // If non-null mouse drag events are forwarded to this view. See - // UpdateActiveMouseView for details. - View* active_mouse_view_; + // ViewStorage id used to store the view mouse drag events are forwarded to. + // See UpdateActiveMouseView() for details. + const int active_mouse_view_id_; internal::MenuControllerDelegate* delegate_; @@ -574,6 +578,10 @@ class VIEWS_EXPORT MenuController : public base::MessageLoop::Dispatcher, // Time when the menu is first shown. base::TimeTicks menu_start_time_; + // If a mouse press triggered this menu, this will have its location (in + // screen coordinates). Otherwise this will be (0, 0). + gfx::Point menu_start_mouse_press_loc_; + DISALLOW_COPY_AND_ASSIGN(MenuController); }; diff --git a/chromium/ui/views/controls/menu/menu_host.cc b/chromium/ui/views/controls/menu/menu_host.cc index 6dea62c6560..f9dd5b2a550 100644 --- a/chromium/ui/views/controls/menu/menu_host.cc +++ b/chromium/ui/views/controls/menu/menu_host.cc @@ -29,6 +29,7 @@ MenuHost::MenuHost(SubmenuView* submenu) : submenu_(submenu), destroying_(false), ignore_capture_lost_(false) { + set_auto_release_capture(false); } MenuHost::~MenuHost() { @@ -109,10 +110,6 @@ internal::RootView* MenuHost::CreateRootView() { return new MenuHostRootView(this, submenu_); } -bool MenuHost::ShouldReleaseCaptureOnMouseReleased() const { - return false; -} - void MenuHost::OnMouseCaptureLost() { if (destroying_ || ignore_capture_lost_) return; diff --git a/chromium/ui/views/controls/menu/menu_host.h b/chromium/ui/views/controls/menu/menu_host.h index 1255a52ef5e..e38cab52b7d 100644 --- a/chromium/ui/views/controls/menu/menu_host.h +++ b/chromium/ui/views/controls/menu/menu_host.h @@ -57,7 +57,6 @@ class MenuHost : public Widget { private: // Overridden from Widget: virtual internal::RootView* CreateRootView() OVERRIDE; - virtual bool ShouldReleaseCaptureOnMouseReleased() const OVERRIDE; virtual void OnMouseCaptureLost() OVERRIDE; virtual void OnNativeWidgetDestroyed() OVERRIDE; virtual void OnOwnerClosing() OVERRIDE; diff --git a/chromium/ui/views/controls/menu/menu_item_view.cc b/chromium/ui/views/controls/menu/menu_item_view.cc index 8d706819875..040cd898616 100644 --- a/chromium/ui/views/controls/menu/menu_item_view.cc +++ b/chromium/ui/views/controls/menu/menu_item_view.cc @@ -227,6 +227,7 @@ MenuItemView* MenuItemView::AddMenuItemAt( int item_id, const string16& label, const string16& sublabel, + const string16& minor_text, const gfx::ImageSkia& icon, Type type, ui::MenuSeparatorType separator_style) { @@ -245,6 +246,7 @@ MenuItemView* MenuItemView::AddMenuItemAt( else item->SetTitle(label); item->SetSubtitle(sublabel); + item->SetMinorText(minor_text); if (!icon.isNull()) item->SetIcon(icon); if (type == SUBMENU) @@ -271,21 +273,21 @@ void MenuItemView::RemoveMenuItemAt(int index) { MenuItemView* MenuItemView::AppendMenuItem(int item_id, const string16& label, Type type) { - return AppendMenuItemImpl(item_id, label, string16(), gfx::ImageSkia(), type, - ui::NORMAL_SEPARATOR); + return AppendMenuItemImpl(item_id, label, string16(), string16(), + gfx::ImageSkia(), type, ui::NORMAL_SEPARATOR); } MenuItemView* MenuItemView::AppendSubMenu(int item_id, const string16& label) { - return AppendMenuItemImpl(item_id, label, string16(), gfx::ImageSkia(), - SUBMENU, ui::NORMAL_SEPARATOR); + return AppendMenuItemImpl(item_id, label, string16(), string16(), + gfx::ImageSkia(), SUBMENU, ui::NORMAL_SEPARATOR); } MenuItemView* MenuItemView::AppendSubMenuWithIcon(int item_id, const string16& label, const gfx::ImageSkia& icon) { - return AppendMenuItemImpl( - item_id, label, string16(), icon, SUBMENU, ui::NORMAL_SEPARATOR); + return AppendMenuItemImpl(item_id, label, string16(), string16(), icon, + SUBMENU, ui::NORMAL_SEPARATOR); } MenuItemView* MenuItemView::AppendMenuItemWithLabel(int item_id, @@ -298,15 +300,15 @@ MenuItemView* MenuItemView::AppendDelegateMenuItem(int item_id) { } void MenuItemView::AppendSeparator() { - AppendMenuItemImpl(0, string16(), string16(), gfx::ImageSkia(), SEPARATOR, - ui::NORMAL_SEPARATOR); + AppendMenuItemImpl(0, string16(), string16(), string16(), gfx::ImageSkia(), + SEPARATOR, ui::NORMAL_SEPARATOR); } MenuItemView* MenuItemView::AppendMenuItemWithIcon(int item_id, const string16& label, const gfx::ImageSkia& icon) { - return AppendMenuItemImpl( - item_id, label, string16(), icon, NORMAL, ui::NORMAL_SEPARATOR); + return AppendMenuItemImpl(item_id, label, string16(), string16(), icon, + NORMAL, ui::NORMAL_SEPARATOR); } MenuItemView* MenuItemView::AppendMenuItemFromModel(ui::MenuModel* model, @@ -314,7 +316,7 @@ MenuItemView* MenuItemView::AppendMenuItemFromModel(ui::MenuModel* model, int id) { gfx::Image icon; model->GetIconAt(index, &icon); - string16 label, sublabel; + string16 label, sublabel, minor_text; ui::MenuSeparatorType separator_style = ui::NORMAL_SEPARATOR; MenuItemView::Type type; ui::MenuModel::ItemType menu_type = model->GetTypeAt(index); @@ -323,16 +325,19 @@ MenuItemView* MenuItemView::AppendMenuItemFromModel(ui::MenuModel* model, type = MenuItemView::NORMAL; label = model->GetLabelAt(index); sublabel = model->GetSublabelAt(index); + minor_text = model->GetMinorTextAt(index); break; case ui::MenuModel::TYPE_CHECK: type = MenuItemView::CHECKBOX; label = model->GetLabelAt(index); sublabel = model->GetSublabelAt(index); + minor_text = model->GetMinorTextAt(index); break; case ui::MenuModel::TYPE_RADIO: type = MenuItemView::RADIO; label = model->GetLabelAt(index); sublabel = model->GetSublabelAt(index); + minor_text = model->GetMinorTextAt(index); break; case ui::MenuModel::TYPE_SEPARATOR: icon = gfx::Image(); @@ -343,6 +348,7 @@ MenuItemView* MenuItemView::AppendMenuItemFromModel(ui::MenuModel* model, type = MenuItemView::SUBMENU; label = model->GetLabelAt(index); sublabel = model->GetSublabelAt(index); + minor_text = model->GetMinorTextAt(index); break; default: NOTREACHED(); @@ -353,6 +359,7 @@ MenuItemView* MenuItemView::AppendMenuItemFromModel(ui::MenuModel* model, return AppendMenuItemImpl(id, label, sublabel, + minor_text, icon.IsEmpty() ? gfx::ImageSkia() : *icon.ToImageSkia(), type, separator_style); @@ -362,11 +369,12 @@ MenuItemView* MenuItemView::AppendMenuItemImpl( int item_id, const string16& label, const string16& sublabel, + const string16& minor_text, const gfx::ImageSkia& icon, Type type, ui::MenuSeparatorType separator_style) { const int index = submenu_ ? submenu_->child_count() : 0; - return AddMenuItemAt(index, item_id, label, sublabel, icon, type, + return AddMenuItemAt(index, item_id, label, sublabel, minor_text, icon, type, separator_style); } @@ -394,6 +402,11 @@ void MenuItemView::SetSubtitle(const string16& subtitle) { invalidate_dimensions(); // Triggers preferred size recalculation. } +void MenuItemView::SetMinorText(const string16& minor_text) { + minor_text_ = minor_text; + invalidate_dimensions(); // Triggers preferred size recalculation. +} + void MenuItemView::SetSelected(bool selected) { selected_ = selected; SchedulePaint(); @@ -851,7 +864,9 @@ void MenuItemView::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) { (!delegate || delegate->ShouldReserveSpaceForSubmenuIndicator() ? item_right_margin_ : config.arrow_to_edge_padding); - gfx::Rect text_bounds(label_start, top_margin, width, available_height); + gfx::Rect text_bounds(label_start, top_margin, width, + subtitle_.empty() ? available_height + : available_height / 2); text_bounds.set_x(GetMirroredXForRect(text_bounds)); int flags = GetDrawStringFlags(); if (mode == PB_FOR_DRAG) @@ -859,6 +874,18 @@ void MenuItemView::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) { canvas->DrawStringInt(title(), font, fg_color, text_bounds.x(), text_bounds.y(), text_bounds.width(), text_bounds.height(), flags); + if (!subtitle_.empty()) { + canvas->DrawStringInt( + subtitle_, + font, + GetNativeTheme()->GetSystemColor( + ui::NativeTheme::kColorId_ButtonDisabledColor), + text_bounds.x(), + text_bounds.y() + GetFont().GetHeight(), + text_bounds.width(), + text_bounds.height(), + flags); + } PaintMinorText(canvas, render_selection); @@ -1003,7 +1030,11 @@ MenuItemView::MenuItemDimensions MenuItemView::CalculateDimensions() { } int label_start = GetLabelStartForThisItem(); - dimensions.standard_width = font.GetStringWidth(title_) + label_start + + int string_width = font.GetStringWidth(title_); + if (!subtitle_.empty()) + string_width = std::max(string_width, font.GetStringWidth(subtitle_)); + + dimensions.standard_width = string_width + label_start + item_right_margin_; // Determine the length of the right-side text. string16 minor_text = GetMinorText(); @@ -1012,6 +1043,7 @@ MenuItemView::MenuItemDimensions MenuItemView::CalculateDimensions() { // Determine the height to use. dimensions.height = std::max(dimensions.height, + (subtitle_.empty() ? 0 : font.GetHeight()) + font.GetHeight() + GetBottomMargin() + GetTopMargin()); dimensions.height = std::max(dimensions.height, GetMenuConfig().item_min_height); @@ -1039,7 +1071,7 @@ string16 MenuItemView::GetMinorText() { return accelerator.GetShortcutText(); } - return subtitle_; + return minor_text_; } bool MenuItemView::IsContainer() const { diff --git a/chromium/ui/views/controls/menu/menu_item_view.h b/chromium/ui/views/controls/menu/menu_item_view.h index e625592c30d..9d641fda56f 100644 --- a/chromium/ui/views/controls/menu/menu_item_view.h +++ b/chromium/ui/views/controls/menu/menu_item_view.h @@ -164,6 +164,7 @@ class VIEWS_EXPORT MenuItemView : public View { int item_id, const string16& label, const string16& sublabel, + const string16& minor_text, const gfx::ImageSkia& icon, Type type, ui::MenuSeparatorType separator_style); @@ -224,6 +225,7 @@ class VIEWS_EXPORT MenuItemView : public View { MenuItemView* AppendMenuItemImpl(int item_id, const string16& label, const string16& sublabel, + const string16& minor_text, const gfx::ImageSkia& icon, Type type, ui::MenuSeparatorType separator_style); @@ -249,6 +251,9 @@ class VIEWS_EXPORT MenuItemView : public View { // Sets the subtitle. void SetSubtitle(const string16& subtitle); + // Sets the minor text. + void SetMinorText(const string16& minor_text); + // Returns the type of this menu. const Type& GetType() const { return type_; } @@ -475,6 +480,9 @@ class VIEWS_EXPORT MenuItemView : public View { // Subtitle/sublabel. string16 subtitle_; + // Minor text. + string16 minor_text_; + // Does the title have a mnemonic? Only useful on the root menu item. bool has_mnemonics_; diff --git a/chromium/ui/views/controls/menu/menu_win.cc b/chromium/ui/views/controls/menu/menu_win.cc index 3ff01b878c8..ac08ec7fb5b 100644 --- a/chromium/ui/views/controls/menu/menu_win.cc +++ b/chromium/ui/views/controls/menu/menu_win.cc @@ -10,13 +10,13 @@ #include "base/stl_util.h" #include "base/strings/string_util.h" #include "ui/base/accelerators/accelerator.h" -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util_win.h" -#include "ui/base/win/window_impl.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/canvas.h" #include "ui/gfx/font.h" #include "ui/gfx/rect.h" +#include "ui/gfx/win/window_impl.h" namespace views { @@ -62,7 +62,7 @@ static int ChromeGetMenuItemID(HMENU hMenu, int pos) { // to intercept right clicks on the HMENU and notify the delegate as well as // for drawing icons. // -class MenuHostWindow : public ui::WindowImpl { +class MenuHostWindow : public gfx::WindowImpl { public: MenuHostWindow(MenuWin* menu, HWND parent_window) : menu_(menu) { int extended_style = 0; diff --git a/chromium/ui/views/controls/menu/native_menu_win.cc b/chromium/ui/views/controls/menu/native_menu_win.cc index e357b1ef3e4..c48a98c5f20 100644 --- a/chromium/ui/views/controls/menu/native_menu_win.cc +++ b/chromium/ui/views/controls/menu/native_menu_win.cc @@ -13,16 +13,16 @@ #include "base/strings/string_util.h" #include "base/win/wrapped_window_proc.h" #include "ui/base/accelerators/accelerator.h" -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util_win.h" #include "ui/base/models/menu_model.h" -#include "ui/base/win/hwnd_util.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/canvas.h" #include "ui/gfx/font.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/rect.h" +#include "ui/gfx/win/hwnd_util.h" #include "ui/native_theme/native_theme.h" #include "ui/native_theme/native_theme_win.h" #include "ui/views/controls/menu/menu_2.h" @@ -81,8 +81,8 @@ class NativeMenuWin::MenuHostWindow { RegisterClass(); hwnd_ = CreateWindowEx(l10n_util::GetExtendedStyles(), kWindowClassName, L"", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL); - ui::CheckWindowCreated(hwnd_); - ui::SetWindowUserData(hwnd_, this); + gfx::CheckWindowCreated(hwnd_); + gfx::SetWindowUserData(hwnd_, this); } ~MenuHostWindow() { @@ -350,7 +350,7 @@ class NativeMenuWin::MenuHostWindow { WPARAM w_param, LPARAM l_param) { MenuHostWindow* host = - reinterpret_cast<MenuHostWindow*>(ui::GetWindowUserData(window)); + reinterpret_cast<MenuHostWindow*>(gfx::GetWindowUserData(window)); // host is null during initial construction. LRESULT l_result = 0; if (!host || !host->ProcessWindowMessage(window, message, w_param, l_param, diff --git a/chromium/ui/views/controls/menu/submenu_view.cc b/chromium/ui/views/controls/menu/submenu_view.cc index fce2983b59c..9184ca9abfb 100644 --- a/chromium/ui/views/controls/menu/submenu_view.cc +++ b/chromium/ui/views/controls/menu/submenu_view.cc @@ -8,7 +8,7 @@ #include "base/compiler_specific.h" #include "ui/base/accessibility/accessible_view_state.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" #include "ui/gfx/canvas.h" #include "ui/views/controls/menu/menu_config.h" #include "ui/views/controls/menu/menu_controller.h" diff --git a/chromium/ui/views/controls/native/native_view_host.cc b/chromium/ui/views/controls/native/native_view_host.cc index a5ae61d33ae..7ec512a5e50 100644 --- a/chromium/ui/views/controls/native/native_view_host.cc +++ b/chromium/ui/views/controls/native/native_view_host.cc @@ -6,6 +6,7 @@ #include "base/logging.h" #include "ui/gfx/canvas.h" +#include "ui/views/accessibility/native_view_accessibility.h" #include "ui/views/controls/native/native_view_host_wrapper.h" #include "ui/views/widget/widget.h" @@ -13,6 +14,7 @@ namespace views { // static const char NativeViewHost::kViewClassName[] = "NativeViewHost"; +const char kWidgetNativeViewHostKey[] = "WidgetNativeViewHost"; #if defined(USE_AURA) // Views implmenetatxion draws the focus. @@ -48,6 +50,10 @@ void NativeViewHost::Attach(gfx::NativeView native_view) { native_wrapper_->NativeViewWillAttach(); Widget::ReparentNativeView(native_view_, GetWidget()->GetNativeView()); Layout(); + + Widget* widget = Widget::GetWidgetForNativeView(native_view); + if (widget) + widget->SetNativeWindowProperty(kWidgetNativeViewHostKey, this); } void NativeViewHost::Detach() { @@ -195,8 +201,12 @@ gfx::NativeViewAccessible NativeViewHost::GetNativeViewAccessible() { void NativeViewHost::Detach(bool destroyed) { if (native_view_) { - if (!destroyed) + if (!destroyed) { + Widget* widget = Widget::GetWidgetForNativeView(native_view_); + if (widget) + widget->SetNativeWindowProperty(kWidgetNativeViewHostKey, NULL); ClearFocus(); + } native_wrapper_->NativeViewDetaching(destroyed); native_view_ = NULL; } diff --git a/chromium/ui/views/controls/native/native_view_host.h b/chromium/ui/views/controls/native/native_view_host.h index c1738f8d789..bdc51510550 100644 --- a/chromium/ui/views/controls/native/native_view_host.h +++ b/chromium/ui/views/controls/native/native_view_host.h @@ -15,6 +15,10 @@ namespace views { class NativeViewHostAuraTest; class NativeViewHostWrapper; +// If a NativeViewHost's native view is a Widget, this native window +// property is set on the widget, pointing to the owning NativeViewHost. +extern const char kWidgetNativeViewHostKey[]; + // A View type that hosts a gfx::NativeView. The bounds of the native view are // kept in sync with the bounds of this view as it is moved and sized. // Under the hood, a platform-specific NativeViewHostWrapper implementation does diff --git a/chromium/ui/views/controls/native/native_view_host_aura.cc b/chromium/ui/views/controls/native/native_view_host_aura.cc index 3a3ed14f80c..444f5803e68 100644 --- a/chromium/ui/views/controls/native/native_view_host_aura.cc +++ b/chromium/ui/views/controls/native/native_view_host_aura.cc @@ -66,7 +66,9 @@ void NativeViewHostAura::RemovedFromWidget() { } void NativeViewHostAura::InstallClip(int x, int y, int w, int h) { - NOTIMPLEMENTED(); + // Note that this does not pose a problem functionality wise - it might + // however pose a speed degradation if not implemented. + LOG(WARNING) << "NativeViewHostAura::InstallClip is not implemented yet."; } bool NativeViewHostAura::HasInstalledClip() { diff --git a/chromium/ui/views/controls/native/native_view_host_unittest.cc b/chromium/ui/views/controls/native/native_view_host_unittest.cc index 0f8eca122b2..f30980bca8b 100644 --- a/chromium/ui/views/controls/native/native_view_host_unittest.cc +++ b/chromium/ui/views/controls/native/native_view_host_unittest.cc @@ -72,33 +72,23 @@ namespace { // times NativeViewHierarchyChanged() is invoked. class NativeViewHierarchyChangedTestView : public View { public: - NativeViewHierarchyChangedTestView() - : attached_count_(0), - detached_count_(0) { + NativeViewHierarchyChangedTestView() : notification_count_(0) { } - void ResetCounts() { - attached_count_ = detached_count_ = 0; + void ResetCount() { + notification_count_ = 0; } - int attached_count() const { return attached_count_; } - int detached_count() const { return detached_count_; } + int notification_count() const { return notification_count_; } // Overriden from View: - virtual void NativeViewHierarchyChanged( - bool attached, - gfx::NativeView native_view, - internal::RootView* root_view) OVERRIDE { - if (attached) - attached_count_++; - else - detached_count_++; - View::NativeViewHierarchyChanged(attached, native_view, root_view); + virtual void NativeViewHierarchyChanged() OVERRIDE { + ++notification_count_; + View::NativeViewHierarchyChanged(); } private: - int attached_count_; - int detached_count_; + int notification_count_; DISALLOW_COPY_AND_ASSIGN(NativeViewHierarchyChangedTestView); }; @@ -158,22 +148,21 @@ TEST_F(NativeViewHostTest, NativeViewHierarchyChanged) { test_view, host)); - EXPECT_EQ(0, test_view->attached_count()); - EXPECT_EQ(0, test_view->detached_count()); - test_view->ResetCounts(); + EXPECT_EQ(0, test_view->notification_count()); + test_view->ResetCount(); - // Detach should send both an attach and detach as well as changing parent. + // Detaching should send a NativeViewHierarchyChanged() notification and + // change the parent. host->Detach(); - EXPECT_EQ(1, test_view->attached_count()); - EXPECT_EQ(1, test_view->detached_count()); + EXPECT_EQ(1, test_view->notification_count()); EXPECT_NE(toplevel()->GetNativeView(), GetNativeParent(child->GetNativeView())); - test_view->ResetCounts(); + test_view->ResetCount(); - // Attaching should send both an attach and detach and reset parent. + // Attaching should send a NativeViewHierarchyChanged() notification and + // reset the parent. host->Attach(child->GetNativeView()); - EXPECT_EQ(1, test_view->attached_count()); - EXPECT_EQ(1, test_view->detached_count()); + EXPECT_EQ(1, test_view->notification_count()); EXPECT_EQ(toplevel()->GetNativeView(), GetNativeParent(child->GetNativeView())); } diff --git a/chromium/ui/views/controls/native/native_view_host_win.cc b/chromium/ui/views/controls/native/native_view_host_win.cc index 24ea19e7ca6..e7b74c3c7a1 100644 --- a/chromium/ui/views/controls/native/native_view_host_win.cc +++ b/chromium/ui/views/controls/native/native_view_host_win.cc @@ -7,10 +7,10 @@ #include <oleacc.h> #include "base/logging.h" -#include "ui/base/win/dpi.h" #include "ui/base/win/hidden_window.h" -#include "ui/base/win/window_impl.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/win/dpi.h" +#include "ui/gfx/win/window_impl.h" #include "ui/views/controls/native/native_view_host.h" #include "ui/views/focus/focus_manager.h" #include "ui/views/widget/native_widget.h" @@ -91,7 +91,7 @@ void NativeViewHostWin::ShowWidget(int x, int y, int w, int h) { SWP_NOCOPYBITS | SWP_NOOWNERZORDER | SWP_NOZORDER; - gfx::Rect bounds = ui::win::DIPToScreenRect(gfx::Rect(x,y,w,h)); + gfx::Rect bounds = gfx::win::DIPToScreenRect(gfx::Rect(x,y,w,h)); // Only send the SHOWWINDOW flag if we're invisible, to avoid flashing. if (!IsWindowVisible(host_->native_view())) diff --git a/chromium/ui/views/controls/native_control.cc b/chromium/ui/views/controls/native_control.cc index e6219e74a1c..3a1fe581016 100644 --- a/chromium/ui/views/controls/native_control.cc +++ b/chromium/ui/views/controls/native_control.cc @@ -13,11 +13,11 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "ui/base/accessibility/accessibility_types.h" -#include "ui/base/keycodes/keyboard_code_conversion_win.h" -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/base/l10n/l10n_util_win.h" #include "ui/base/view_prop.h" -#include "ui/base/win/hwnd_util.h" +#include "ui/events/keycodes/keyboard_code_conversion_win.h" +#include "ui/events/keycodes/keyboard_codes.h" +#include "ui/gfx/win/hwnd_util.h" #include "ui/views/background.h" #include "ui/views/controls/native/native_view_host.h" #include "ui/views/focus/focus_manager.h" @@ -88,7 +88,7 @@ class NativeControlContainer : public CWindowImpl<NativeControlContainer, control_ = parent_->CreateNativeControl(m_hWnd); // We subclass the control hwnd so we get the WM_KEYDOWN messages. - original_handler_ = ui::SetWindowProc( + original_handler_ = gfx::SetWindowProc( control_, &NativeControl::NativeControlWndProc); prop_.reset(new ViewProp(control_, kNativeControlKey , parent_)); @@ -378,7 +378,7 @@ LRESULT CALLBACK NativeControl::NativeControlWndProc(HWND window, NOTREACHED(); } } else if (message == WM_DESTROY) { - ui::SetWindowProc(window, reinterpret_cast<WNDPROC>(original_handler)); + gfx::SetWindowProc(window, reinterpret_cast<WNDPROC>(original_handler)); native_control->container_->prop_.reset(); } diff --git a/chromium/ui/views/controls/native_control.h b/chromium/ui/views/controls/native_control.h index 2ec731e278a..80aa5887cf1 100644 --- a/chromium/ui/views/controls/native_control.h +++ b/chromium/ui/views/controls/native_control.h @@ -7,7 +7,7 @@ #include <windows.h> -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/views/view.h" namespace views { diff --git a/chromium/ui/views/controls/native_control_win.cc b/chromium/ui/views/controls/native_control_win.cc index 2b6c6d42571..c50411d13f5 100644 --- a/chromium/ui/views/controls/native_control_win.cc +++ b/chromium/ui/views/controls/native_control_win.cc @@ -10,7 +10,7 @@ #include "ui/base/accessibility/accessibility_types.h" #include "ui/base/l10n/l10n_util_win.h" #include "ui/base/view_prop.h" -#include "ui/base/win/hwnd_util.h" +#include "ui/gfx/win/hwnd_util.h" #include "ui/views/controls/combobox/combobox.h" #include "ui/views/focus/focus_manager.h" #include "ui/views/widget/widget.h" @@ -139,7 +139,7 @@ void NativeControlWin::NativeControlCreated(HWND native_control) { props_.push_back(ChildWindowMessageProcessor::Register(native_control, this)); // Subclass so we get WM_KEYDOWN and WM_SETFOCUS messages. - original_wndproc_ = ui::SetWindowProc( + original_wndproc_ = gfx::SetWindowProc( native_control, &NativeControlWin::NativeControlWndProc); Attach(native_control); @@ -216,7 +216,7 @@ LRESULT NativeControlWin::NativeControlWndProc(HWND window, } } else if (message == WM_DESTROY) { native_control->props_.clear(); - ui::SetWindowProc(window, native_control->original_wndproc_); + gfx::SetWindowProc(window, native_control->original_wndproc_); } return CallWindowProc(native_control->original_wndproc_, window, message, diff --git a/chromium/ui/views/controls/prefix_selector.cc b/chromium/ui/views/controls/prefix_selector.cc index 6d6e0809c8b..91659bc2a29 100644 --- a/chromium/ui/views/controls/prefix_selector.cc +++ b/chromium/ui/views/controls/prefix_selector.cc @@ -6,7 +6,7 @@ #include "base/i18n/case_conversion.h" #include "ui/base/ime/text_input_type.h" -#include "ui/base/range/range.h" +#include "ui/gfx/range/range.h" #include "ui/views/controls/prefix_delegate.h" #include "ui/views/widget/widget.h" @@ -91,30 +91,30 @@ bool PrefixSelector::HasCompositionText() { return false; } -bool PrefixSelector::GetTextRange(ui::Range* range) { - *range = ui::Range(); +bool PrefixSelector::GetTextRange(gfx::Range* range) { + *range = gfx::Range(); return false; } -bool PrefixSelector::GetCompositionTextRange(ui::Range* range) { - *range = ui::Range(); +bool PrefixSelector::GetCompositionTextRange(gfx::Range* range) { + *range = gfx::Range(); return false; } -bool PrefixSelector::GetSelectionRange(ui::Range* range) { - *range = ui::Range(); +bool PrefixSelector::GetSelectionRange(gfx::Range* range) { + *range = gfx::Range(); return false; } -bool PrefixSelector::SetSelectionRange(const ui::Range& range) { +bool PrefixSelector::SetSelectionRange(const gfx::Range& range) { return false; } -bool PrefixSelector::DeleteRange(const ui::Range& range) { +bool PrefixSelector::DeleteRange(const gfx::Range& range) { return false; } -bool PrefixSelector::GetTextFromRange(const ui::Range& range, +bool PrefixSelector::GetTextFromRange(const gfx::Range& range, string16* text) { return false; } @@ -135,9 +135,11 @@ void PrefixSelector::EnsureCaretInRect(const gfx::Rect& rect) { } void PrefixSelector::OnTextInput(const string16& text) { - // Small hack to filter out 'tab' input, as the expectation is that tabs - // should cycle input elements, not influence selection. - if (text.length() == 1 && text.at(0) == 0x09) + // Small hack to filter out 'tab' and 'enter' input, as the expectation is + // that they are control characters and will not affect the currently-active + // prefix. + if (text.length() == 1 && + (text[0] == L'\t' || text[0] == L'\r' || text[0] == L'\n')) return; const int row_count = prefix_delegate_->GetRowCount(); diff --git a/chromium/ui/views/controls/prefix_selector.h b/chromium/ui/views/controls/prefix_selector.h index 629c306449b..2c580086441 100644 --- a/chromium/ui/views/controls/prefix_selector.h +++ b/chromium/ui/views/controls/prefix_selector.h @@ -39,12 +39,12 @@ class VIEWS_EXPORT PrefixSelector : public ui::TextInputClient { virtual bool GetCompositionCharacterBounds(uint32 index, gfx::Rect* rect) OVERRIDE; virtual bool HasCompositionText() OVERRIDE; - virtual bool GetTextRange(ui::Range* range) OVERRIDE; - virtual bool GetCompositionTextRange(ui::Range* range) OVERRIDE; - virtual bool GetSelectionRange(ui::Range* range) OVERRIDE; - virtual bool SetSelectionRange(const ui::Range& range) OVERRIDE; - virtual bool DeleteRange(const ui::Range& range) OVERRIDE; - virtual bool GetTextFromRange(const ui::Range& range, + virtual bool GetTextRange(gfx::Range* range) OVERRIDE; + virtual bool GetCompositionTextRange(gfx::Range* range) OVERRIDE; + virtual bool GetSelectionRange(gfx::Range* range) OVERRIDE; + virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE; + virtual bool DeleteRange(const gfx::Range& range) OVERRIDE; + virtual bool GetTextFromRange(const gfx::Range& range, string16* text) OVERRIDE; virtual void OnInputMethodChanged() OVERRIDE; virtual bool ChangeTextDirectionAndLayoutAlignment( diff --git a/chromium/ui/views/controls/scroll_view.cc b/chromium/ui/views/controls/scroll_view.cc index 11ffc020ea7..d835c1ebdf8 100644 --- a/chromium/ui/views/controls/scroll_view.cc +++ b/chromium/ui/views/controls/scroll_view.cc @@ -5,7 +5,7 @@ #include "ui/views/controls/scroll_view.h" #include "base/logging.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" #include "ui/native_theme/native_theme.h" #include "ui/views/border.h" #include "ui/views/controls/scrollbar/native_scroll_bar.h" diff --git a/chromium/ui/views/controls/scrollbar/base_scroll_bar.cc b/chromium/ui/views/controls/scrollbar/base_scroll_bar.cc index 38c025676e0..6271c2e1bfe 100644 --- a/chromium/ui/views/controls/scrollbar/base_scroll_bar.cc +++ b/chromium/ui/views/controls/scrollbar/base_scroll_bar.cc @@ -13,9 +13,9 @@ #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "grit/ui_strings.h" -#include "ui/base/events/event.h" -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/canvas.h" #include "ui/views/controls/menu/menu_item_view.h" #include "ui/views/controls/menu/menu_runner.h" diff --git a/chromium/ui/views/controls/scrollbar/bitmap_scroll_bar.cc b/chromium/ui/views/controls/scrollbar/bitmap_scroll_bar.cc index 7ba82e41140..2597cee0b78 100644 --- a/chromium/ui/views/controls/scrollbar/bitmap_scroll_bar.cc +++ b/chromium/ui/views/controls/scrollbar/bitmap_scroll_bar.cc @@ -13,8 +13,8 @@ #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "grit/ui_strings.h" -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/canvas.h" #include "ui/gfx/image/image_skia.h" #include "ui/views/controls/menu/menu.h" diff --git a/chromium/ui/views/controls/scrollbar/native_scroll_bar.cc b/chromium/ui/views/controls/scrollbar/native_scroll_bar.cc index de2ec37bba5..9a913709a4b 100644 --- a/chromium/ui/views/controls/scrollbar/native_scroll_bar.cc +++ b/chromium/ui/views/controls/scrollbar/native_scroll_bar.cc @@ -8,7 +8,7 @@ #include <string> #include "base/message_loop/message_loop.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" #include "ui/views/controls/scrollbar/native_scroll_bar_wrapper.h" #include "ui/views/widget/widget.h" diff --git a/chromium/ui/views/controls/scrollbar/native_scroll_bar_views.cc b/chromium/ui/views/controls/scrollbar/native_scroll_bar_views.cc index aa812a894e5..6c3506f515c 100644 --- a/chromium/ui/views/controls/scrollbar/native_scroll_bar_views.cc +++ b/chromium/ui/views/controls/scrollbar/native_scroll_bar_views.cc @@ -5,7 +5,7 @@ #include "ui/views/controls/scrollbar/native_scroll_bar_views.h" #include "base/logging.h" -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/canvas.h" #include "ui/gfx/path.h" #include "ui/views/controls/button/custom_button.h" diff --git a/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc b/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc index 25228e45a4d..176f7b9554e 100644 --- a/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc +++ b/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc @@ -23,7 +23,7 @@ const int kThumbHoverAlpha = 128; const int kThumbDefaultAlpha = 64; class OverlayScrollBarThumb : public BaseScrollBarThumb, - public ui::AnimationDelegate { + public gfx::AnimationDelegate { public: explicit OverlayScrollBarThumb(BaseScrollBar* scroll_bar); virtual ~OverlayScrollBarThumb(); @@ -33,8 +33,8 @@ class OverlayScrollBarThumb : public BaseScrollBarThumb, virtual gfx::Size GetPreferredSize() OVERRIDE; virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; - // ui::AnimationDelegate overrides: - virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; + // gfx::AnimationDelegate overrides: + virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; private: double animation_opacity_; @@ -77,7 +77,7 @@ void OverlayScrollBarThumb::OnPaint(gfx::Canvas* canvas) { } void OverlayScrollBarThumb::AnimationProgressed( - const ui::Animation* animation) { + const gfx::Animation* animation) { animation_opacity_ = animation->GetCurrentValue(); SchedulePaint(); } diff --git a/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.h b/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.h index ac64d356097..b061da08586 100644 --- a/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.h +++ b/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.h @@ -5,7 +5,7 @@ #ifndef UI_VIEWS_CONTROLS_SCROLLBAR_OVERLAY_SCROLL_BAR_H_ #define UI_VIEWS_CONTROLS_SCROLLBAR_OVERLAY_SCROLL_BAR_H_ -#include "ui/base/animation/slide_animation.h" +#include "ui/gfx/animation/slide_animation.h" #include "ui/views/controls/scrollbar/base_scroll_bar.h" namespace views { @@ -33,7 +33,7 @@ class VIEWS_EXPORT OverlayScrollBar : public BaseScrollBar { virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; private: - ui::SlideAnimation animation_; + gfx::SlideAnimation animation_; DISALLOW_COPY_AND_ASSIGN(OverlayScrollBar); }; diff --git a/chromium/ui/views/controls/slider.cc b/chromium/ui/views/controls/slider.cc index 2b74121c1e4..0a5c7f050cb 100644 --- a/chromium/ui/views/controls/slider.cc +++ b/chromium/ui/views/controls/slider.cc @@ -13,9 +13,9 @@ #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkPaint.h" #include "ui/base/accessibility/accessible_view_state.h" -#include "ui/base/animation/slide_animation.h" -#include "ui/base/events/event.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/events/event.h" +#include "ui/gfx/animation/slide_animation.h" #include "ui/gfx/canvas.h" #include "ui/gfx/point.h" #include "ui/gfx/rect.h" @@ -95,7 +95,7 @@ void Slider::SetValueInternal(float value, SliderChangeReason reason) { // Do not animate when setting the value of the slider for the first time. // There is no message-loop when running tests. So we cannot animate then. animating_value_ = old_value; - move_animation_.reset(new ui::SlideAnimation(this)); + move_animation_.reset(new gfx::SlideAnimation(this)); move_animation_->SetSlideDuration(kSlideValueChangeDurationMS); move_animation_->Show(); AnimationProgressed(move_animation_.get()); @@ -304,7 +304,7 @@ void Slider::OnGestureEvent(ui::GestureEvent* event) { } } -void Slider::AnimationProgressed(const ui::Animation* animation) { +void Slider::AnimationProgressed(const gfx::Animation* animation) { animating_value_ = animation->CurrentValueBetween(animating_value_, value_); SchedulePaint(); } diff --git a/chromium/ui/views/controls/slider.h b/chromium/ui/views/controls/slider.h index 5cfd3f5aaec..3c17e94af25 100644 --- a/chromium/ui/views/controls/slider.h +++ b/chromium/ui/views/controls/slider.h @@ -5,7 +5,7 @@ #ifndef UI_VIEWS_CONTROLS_SLIDER_H_ #define UI_VIEWS_CONTROLS_SLIDER_H_ -#include "ui/base/animation/animation_delegate.h" +#include "ui/gfx/animation/animation_delegate.h" #include "ui/views/view.h" #include "ui/views/views_export.h" @@ -13,9 +13,6 @@ typedef unsigned int SkColor; namespace gfx { class ImageSkia; -} - -namespace ui { class SlideAnimation; } @@ -45,7 +42,7 @@ class VIEWS_EXPORT SliderListener { }; class VIEWS_EXPORT Slider : public View, - public ui::AnimationDelegate { + public gfx::AnimationDelegate { public: enum Orientation { HORIZONTAL, @@ -96,13 +93,13 @@ class VIEWS_EXPORT Slider : public View, // ui::EventHandler overrides: virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; - // ui::AnimationDelegate overrides: - virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; + // gfx::AnimationDelegate overrides: + virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; SliderListener* listener_; Orientation orientation_; - scoped_ptr<ui::SlideAnimation> move_animation_; + scoped_ptr<gfx::SlideAnimation> move_animation_; float value_; float keyboard_increment_; diff --git a/chromium/ui/views/controls/styled_label.cc b/chromium/ui/views/controls/styled_label.cc index d679ac13ee5..e23e40c4628 100644 --- a/chromium/ui/views/controls/styled_label.cc +++ b/chromium/ui/views/controls/styled_label.cc @@ -7,7 +7,7 @@ #include <vector> #include "base/strings/string_util.h" -#include "ui/base/text/text_elider.h" +#include "ui/gfx/text_elider.h" #include "ui/native_theme/native_theme.h" #include "ui/views/controls/label.h" #include "ui/views/controls/link.h" @@ -82,7 +82,8 @@ bool StyledLabel::StyleRange::operator<( StyledLabel::StyledLabel(const string16& text, StyledLabelListener* listener) : listener_(listener), - displayed_on_background_color_set_(false) { + displayed_on_background_color_set_(false), + auto_color_readability_enabled_(true) { TrimWhitespace(text, TRIM_TRAILING, &text_); } @@ -95,11 +96,11 @@ void StyledLabel::SetText(const string16& text) { PreferredSizeChanged(); } -void StyledLabel::AddStyleRange(const ui::Range& range, +void StyledLabel::AddStyleRange(const gfx::Range& range, const RangeStyleInfo& style_info) { DCHECK(!range.is_reversed()); DCHECK(!range.is_empty()); - DCHECK(ui::Range(0, text_.size()).Contains(range)); + DCHECK(gfx::Range(0, text_.size()).Contains(range)); style_ranges_.push(StyleRange(range, style_info)); @@ -172,7 +173,7 @@ int StyledLabel::CalculateAndDoLayout(int width, bool dry_run) { if (x == 0 && line > 0) TrimWhitespace(remaining_string, TRIM_LEADING, &remaining_string); - ui::Range range(ui::Range::InvalidRange()); + gfx::Range range(gfx::Range::InvalidRange()); if (!style_ranges.empty()) range = style_ranges.top().range; @@ -188,11 +189,11 @@ int StyledLabel::CalculateAndDoLayout(int width, bool dry_run) { text_font = text_font.DeriveFont(0, style_ranges.top().style_info.font_style); } - ui::ElideRectangleText(remaining_string, + gfx::ElideRectangleText(remaining_string, text_font, chunk_bounds.width(), chunk_bounds.height(), - ui::IGNORE_LONG_WORDS, + gfx::IGNORE_LONG_WORDS, &substrings); DCHECK(!substrings.empty()); @@ -246,6 +247,7 @@ int StyledLabel::CalculateAndDoLayout(int width, bool dry_run) { if (displayed_on_background_color_set_) label->SetBackgroundColor(displayed_on_background_color_); + label->SetAutoColorReadabilityEnabled(auto_color_readability_enabled_); // Lay out the views to overlap by 1 pixel to compensate for their border // spacing. Otherwise, "<a>link</a>," will render as "link ,". diff --git a/chromium/ui/views/controls/styled_label.h b/chromium/ui/views/controls/styled_label.h index bc22a18ea1f..adf5993a767 100644 --- a/chromium/ui/views/controls/styled_label.h +++ b/chromium/ui/views/controls/styled_label.h @@ -11,7 +11,7 @@ #include "base/basictypes.h" #include "base/strings/string16.h" #include "third_party/skia/include/core/SkColor.h" -#include "ui/base/range/range.h" +#include "ui/gfx/range/range.h" #include "ui/gfx/size.h" #include "ui/views/controls/link_listener.h" #include "ui/views/view.h" @@ -62,7 +62,7 @@ class VIEWS_EXPORT StyledLabel : public View, public LinkListener { // Marks the given range within |text_| with style defined by |style_info|. // |range| must be contained in |text_|. - void AddStyleRange(const ui::Range& range, const RangeStyleInfo& style_info); + void AddStyleRange(const gfx::Range& range, const RangeStyleInfo& style_info); // Sets the default style to use for any part of the text that isn't within // a range set by AddStyleRange. @@ -76,6 +76,10 @@ class VIEWS_EXPORT StyledLabel : public View, public LinkListener { return displayed_on_background_color_; } + void set_auto_color_readability_enabled(bool auto_color_readability) { + auto_color_readability_enabled_ = auto_color_readability; + } + // View implementation: virtual gfx::Insets GetInsets() const OVERRIDE; virtual int GetHeightForWidth(int w) OVERRIDE; @@ -87,7 +91,7 @@ class VIEWS_EXPORT StyledLabel : public View, public LinkListener { private: struct StyleRange { - StyleRange(const ui::Range& range, + StyleRange(const gfx::Range& range, const RangeStyleInfo& style_info) : range(range), style_info(style_info) { @@ -96,7 +100,7 @@ class VIEWS_EXPORT StyledLabel : public View, public LinkListener { bool operator<(const StyleRange& other) const; - ui::Range range; + gfx::Range range; RangeStyleInfo style_info; }; @@ -121,7 +125,7 @@ class VIEWS_EXPORT StyledLabel : public View, public LinkListener { // A mapping from a view to the range it corresponds to in |text_|. Only views // that correspond to ranges with is_link style set will be added to the map. - std::map<View*, ui::Range> link_targets_; + std::map<View*, gfx::Range> link_targets_; // This variable saves the result of the last GetHeightForWidth call in order // to avoid repeated calculation. @@ -131,6 +135,10 @@ class VIEWS_EXPORT StyledLabel : public View, public LinkListener { SkColor displayed_on_background_color_; bool displayed_on_background_color_set_; + // Controls whether the text is automatically re-colored to be readable on the + // background. + bool auto_color_readability_enabled_; + DISALLOW_COPY_AND_ASSIGN(StyledLabel); }; diff --git a/chromium/ui/views/controls/styled_label_listener.h b/chromium/ui/views/controls/styled_label_listener.h index 390865c797f..13c08fd6e97 100644 --- a/chromium/ui/views/controls/styled_label_listener.h +++ b/chromium/ui/views/controls/styled_label_listener.h @@ -7,7 +7,7 @@ #include "ui/views/views_export.h" -namespace ui { +namespace gfx { class Range; } @@ -16,7 +16,7 @@ namespace views { // A listener interface for StyledLabel. class VIEWS_EXPORT StyledLabelListener { public: - virtual void StyledLabelLinkClicked(const ui::Range& range, + virtual void StyledLabelLinkClicked(const gfx::Range& range, int event_flags) = 0; protected: diff --git a/chromium/ui/views/controls/styled_label_unittest.cc b/chromium/ui/views/controls/styled_label_unittest.cc index 3e2b15354b6..dac53930f2f 100644 --- a/chromium/ui/views/controls/styled_label_unittest.cc +++ b/chromium/ui/views/controls/styled_label_unittest.cc @@ -21,7 +21,7 @@ class StyledLabelTest : public testing::Test, public StyledLabelListener { virtual ~StyledLabelTest() {} // StyledLabelListener implementation. - virtual void StyledLabelLinkClicked(const ui::Range& range, + virtual void StyledLabelLinkClicked(const gfx::Range& range, int event_flags) OVERRIDE {} protected: @@ -121,13 +121,13 @@ TEST_F(StyledLabelTest, BasicWrapping) { TEST_F(StyledLabelTest, CreateLinks) { const std::string text("This is a test block of text."); InitStyledLabel(text); - styled()->AddStyleRange(ui::Range(0, 1), + styled()->AddStyleRange(gfx::Range(0, 1), StyledLabel::RangeStyleInfo::CreateForLink()); - styled()->AddStyleRange(ui::Range(1, 2), + styled()->AddStyleRange(gfx::Range(1, 2), StyledLabel::RangeStyleInfo::CreateForLink()); - styled()->AddStyleRange(ui::Range(10, 11), + styled()->AddStyleRange(gfx::Range(10, 11), StyledLabel::RangeStyleInfo::CreateForLink()); - styled()->AddStyleRange(ui::Range(12, 13), + styled()->AddStyleRange(gfx::Range(12, 13), StyledLabel::RangeStyleInfo::CreateForLink()); styled()->SetBounds(0, 0, 1000, 1000); @@ -140,7 +140,7 @@ TEST_F(StyledLabelTest, DontBreakLinks) { const std::string link_text("and this should be a link"); InitStyledLabel(text + link_text); styled()->AddStyleRange( - ui::Range(text.size(), text.size() + link_text.size()), + gfx::Range(text.size(), text.size() + link_text.size()), StyledLabel::RangeStyleInfo::CreateForLink()); Label label(ASCIIToUTF16(text + link_text.substr(0, link_text.size() / 2))); @@ -163,7 +163,7 @@ TEST_F(StyledLabelTest, StyledRangeWithDisabledLineWrapping) { StyledLabel::RangeStyleInfo style_info; style_info.disable_line_wrapping = true; styled()->AddStyleRange( - ui::Range(text.size(), text.size() + unbreakable_text.size()), + gfx::Range(text.size(), text.size() + unbreakable_text.size()), style_info); Label label(ASCIIToUTF16( @@ -187,7 +187,7 @@ TEST_F(StyledLabelTest, StyledRangeUnderlined) { StyledLabel::RangeStyleInfo style_info; style_info.font_style = gfx::Font::UNDERLINE; styled()->AddStyleRange( - ui::Range(text.size(), text.size() + underlined_text.size()), + gfx::Range(text.size(), text.size() + underlined_text.size()), style_info); styled()->SetBounds(0, 0, 1000, 1000); @@ -208,7 +208,7 @@ TEST_F(StyledLabelTest, StyledRangeBold) { StyledLabel::RangeStyleInfo style_info; style_info.font_style = gfx::Font::BOLD; - styled()->AddStyleRange(ui::Range(0, bold_text.size()), style_info); + styled()->AddStyleRange(gfx::Range(0, bold_text.size()), style_info); // Calculate the bold text width if it were a pure label view, both with bold // and normal style. @@ -265,11 +265,11 @@ TEST_F(StyledLabelTest, Color) { StyledLabel::RangeStyleInfo style_info_red; style_info_red.color = SK_ColorRED; - styled()->AddStyleRange(ui::Range(0, text_red.size()), style_info_red); + styled()->AddStyleRange(gfx::Range(0, text_red.size()), style_info_red); StyledLabel::RangeStyleInfo style_info_link = StyledLabel::RangeStyleInfo::CreateForLink(); - styled()->AddStyleRange(ui::Range(text_red.size(), + styled()->AddStyleRange(gfx::Range(text_red.size(), text_red.size() + text_link.size()), style_info_link); @@ -323,9 +323,9 @@ TEST_F(StyledLabelTest, StyledRangeWithTooltip) { StyledLabel::RangeStyleInfo tooltip_style; tooltip_style.tooltip = ASCIIToUTF16("tooltip"); styled()->AddStyleRange( - ui::Range(tooltip_start, tooltip_start + tooltip_text.size()), + gfx::Range(tooltip_start, tooltip_start + tooltip_text.size()), tooltip_style); - styled()->AddStyleRange(ui::Range(link_start, link_start + link_text.size()), + styled()->AddStyleRange(gfx::Range(link_start, link_start + link_text.size()), StyledLabel::RangeStyleInfo::CreateForLink()); // Break line inside the range with the tooltip. diff --git a/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc b/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc index cb2b595294f..65021d240cb 100644 --- a/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc +++ b/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc @@ -6,7 +6,7 @@ #include "base/logging.h" #include "ui/base/accessibility/accessible_view_state.h" -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/canvas.h" #include "ui/gfx/font.h" #include "ui/views/controls/label.h" @@ -230,7 +230,7 @@ void TabStrip::OnPaint(gfx::Canvas* canvas) { SkIntToScalar(selected_tab->height()) - kTabBorderThickness; SkScalar tab_width = SkIntToScalar(selected_tab->width()) - kTabBorderThickness; - SkScalar tab_start = SkIntToScalar(selected_tab->x()); + SkScalar tab_start = SkIntToScalar(selected_tab->GetMirroredX()); path.moveTo(0, line_y); path.rLineTo(tab_start, 0); path.rLineTo(0, -tab_height); diff --git a/chromium/ui/views/controls/table/table_view.cc b/chromium/ui/views/controls/table/table_view.cc index 48dd4c48776..c655eb686ad 100644 --- a/chromium/ui/views/controls/table/table_view.cc +++ b/chromium/ui/views/controls/table/table_view.cc @@ -8,7 +8,7 @@ #include "base/auto_reset.h" #include "base/i18n/rtl.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" #include "ui/gfx/canvas.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/rect_conversions.h" diff --git a/chromium/ui/views/controls/table/table_view_observer.h b/chromium/ui/views/controls/table/table_view_observer.h index bd2ff367ab4..44400eee1c7 100644 --- a/chromium/ui/views/controls/table/table_view_observer.h +++ b/chromium/ui/views/controls/table/table_view_observer.h @@ -5,7 +5,7 @@ #ifndef UI_VIEWS_CONTROLS_TABLE_TABLE_VIEW_OBSERVER_H_ #define UI_VIEWS_CONTROLS_TABLE_TABLE_VIEW_OBSERVER_H_ -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/keycodes/keyboard_codes.h" namespace views { diff --git a/chromium/ui/views/controls/textfield/native_textfield_views.cc b/chromium/ui/views/controls/textfield/native_textfield_views.cc index 822bbdf5fb0..3f74efcccd2 100644 --- a/chromium/ui/views/controls/textfield/native_textfield_views.cc +++ b/chromium/ui/views/controls/textfield/native_textfield_views.cc @@ -19,13 +19,13 @@ #include "ui/base/clipboard/clipboard.h" #include "ui/base/dragdrop/drag_drop_types.h" #include "ui/base/dragdrop/drag_utils.h" -#include "ui/base/events/event.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/range/range.h" #include "ui/base/ui_base_switches_util.h" #include "ui/compositor/layer.h" +#include "ui/events/event.h" #include "ui/gfx/canvas.h" #include "ui/gfx/insets.h" +#include "ui/gfx/range/range.h" #include "ui/gfx/render_text.h" #include "ui/gfx/text_constants.h" #include "ui/native_theme/native_theme.h" @@ -130,7 +130,7 @@ bool NativeTextfieldViews::OnMouseDragged(const ui::MouseEvent& event) { if (aggregated_clicks_ == 1) { model_->SelectWord(); // Expand the selection so the initially selected word remains selected. - ui::Range selection = GetRenderText()->selection(); + gfx::Range selection = GetRenderText()->selection(); const size_t min = std::min(selection.GetMin(), double_click_word_.GetMin()); const size_t max = std::max(selection.GetMax(), @@ -273,10 +273,10 @@ bool NativeTextfieldViews::CanDrop(const OSExchangeData& data) { int NativeTextfieldViews::OnDragUpdated(const ui::DropTargetEvent& event) { DCHECK(CanDrop(event.data())); - const ui::Range& selection = GetRenderText()->selection(); + const gfx::Range& selection = GetRenderText()->selection(); drop_cursor_position_ = GetRenderText()->FindCursorPosition(event.location()); bool in_selection = !selection.is_empty() && - selection.Contains(ui::Range(drop_cursor_position_.caret_pos())); + selection.Contains(gfx::Range(drop_cursor_position_.caret_pos())); is_drop_cursor_visible_ = !in_selection; // TODO(msw): Pan over text when the user drags to the visible text edge. OnCaretBoundsChanged(); @@ -325,7 +325,7 @@ int NativeTextfieldViews::OnPerformDrop(const ui::DropTargetEvent& event) { if (move) { // Adjust the drop destination if it is on or after the current selection. size_t drop = drop_destination_model.caret_pos(); - drop -= GetSelectedRange().Intersect(ui::Range(0, drop)).length(); + drop -= GetSelectedRange().Intersect(gfx::Range(0, drop)).length(); model_->DeleteSelectionAndInsertTextAt(text, drop); } else { model_->MoveCursorTo(drop_destination_model); @@ -371,7 +371,7 @@ void NativeTextfieldViews::SelectRect(const gfx::Point& start, gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start); gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end); gfx::SelectionModel selection( - ui::Range(start_caret.caret_pos(), end_caret.caret_pos()), + gfx::Range(start_caret.caret_pos(), end_caret.caret_pos()), end_caret.caret_affinity()); OnBeforeUserAction(); @@ -629,11 +629,11 @@ bool NativeTextfieldViews::IsIMEComposing() const { return model_->HasCompositionText(); } -ui::Range NativeTextfieldViews::GetSelectedRange() const { +gfx::Range NativeTextfieldViews::GetSelectedRange() const { return GetRenderText()->selection(); } -void NativeTextfieldViews::SelectRange(const ui::Range& range) { +void NativeTextfieldViews::SelectRange(const gfx::Range& range) { model_->SelectRange(range); OnCaretBoundsChanged(); SchedulePaint(); @@ -719,7 +719,7 @@ int NativeTextfieldViews::GetFontHeight() { } int NativeTextfieldViews::GetTextfieldBaseline() const { - return GetRenderText()->font_list().GetBaseline(); + return GetRenderText()->GetBaseline(); } int NativeTextfieldViews::GetWidthNeededForText() const { @@ -734,6 +734,10 @@ bool NativeTextfieldViews::HasTextBeingDragged() { return initiating_drag_; } +gfx::Point NativeTextfieldViews::GetContextMenuLocation() { + return GetCaretBounds().bottom_right(); +} + ///////////////////////////////////////////////////////////////// // NativeTextfieldViews, ui::SimpleMenuModel::Delegate overrides: @@ -745,6 +749,8 @@ bool NativeTextfieldViews::IsCommandIdEnabled(int command_id) const { bool editable = !textfield_->read_only(); string16 result; switch (command_id) { + case IDS_APP_UNDO: + return editable && model_->CanUndo(); case IDS_APP_CUT: return editable && model_->HasSelection() && !textfield_->IsObscured(); case IDS_APP_COPY: @@ -788,6 +794,12 @@ void NativeTextfieldViews::ExecuteCommand(int command_id, int event_flags) { } else { bool text_changed = false; switch (command_id) { + case IDS_APP_UNDO: + OnBeforeUserAction(); + text_changed = model_->Undo(); + UpdateAfterChange(text_changed, text_changed); + OnAfterUserAction(); + break; case IDS_APP_CUT: OnBeforeUserAction(); text_changed = Cut(); @@ -829,7 +841,7 @@ void NativeTextfieldViews::SetColor(SkColor value) { SchedulePaint(); } -void NativeTextfieldViews::ApplyColor(SkColor value, const ui::Range& range) { +void NativeTextfieldViews::ApplyColor(SkColor value, const gfx::Range& range) { GetRenderText()->ApplyColor(value, range); SchedulePaint(); } @@ -841,7 +853,7 @@ void NativeTextfieldViews::SetStyle(gfx::TextStyle style, bool value) { void NativeTextfieldViews::ApplyStyle(gfx::TextStyle style, bool value, - const ui::Range& range) { + const gfx::Range& range) { GetRenderText()->ApplyStyle(style, value, range); SchedulePaint(); } @@ -983,7 +995,7 @@ bool NativeTextfieldViews::GetCompositionCharacterBounds(uint32 index, DCHECK(rect); if (!HasCompositionText()) return false; - const ui::Range& composition_range = GetRenderText()->GetCompositionRange(); + const gfx::Range& composition_range = GetRenderText()->GetCompositionRange(); const uint32 left_cursor_pos = composition_range.start() + index; const uint32 right_cursor_pos = composition_range.start() + index + 1; DCHECK(!composition_range.is_empty()); @@ -1012,7 +1024,7 @@ bool NativeTextfieldViews::HasCompositionText() { return model_->HasCompositionText(); } -bool NativeTextfieldViews::GetTextRange(ui::Range* range) { +bool NativeTextfieldViews::GetTextRange(gfx::Range* range) { if (!ImeEditingAllowed()) return false; @@ -1020,7 +1032,7 @@ bool NativeTextfieldViews::GetTextRange(ui::Range* range) { return true; } -bool NativeTextfieldViews::GetCompositionTextRange(ui::Range* range) { +bool NativeTextfieldViews::GetCompositionTextRange(gfx::Range* range) { if (!ImeEditingAllowed()) return false; @@ -1028,14 +1040,14 @@ bool NativeTextfieldViews::GetCompositionTextRange(ui::Range* range) { return true; } -bool NativeTextfieldViews::GetSelectionRange(ui::Range* range) { +bool NativeTextfieldViews::GetSelectionRange(gfx::Range* range) { if (!ImeEditingAllowed()) return false; *range = GetSelectedRange(); return true; } -bool NativeTextfieldViews::SetSelectionRange(const ui::Range& range) { +bool NativeTextfieldViews::SetSelectionRange(const gfx::Range& range) { if (!ImeEditingAllowed() || !range.IsValid()) return false; @@ -1045,7 +1057,7 @@ bool NativeTextfieldViews::SetSelectionRange(const ui::Range& range) { return true; } -bool NativeTextfieldViews::DeleteRange(const ui::Range& range) { +bool NativeTextfieldViews::DeleteRange(const gfx::Range& range) { if (!ImeEditingAllowed() || range.is_empty()) return false; @@ -1060,12 +1072,12 @@ bool NativeTextfieldViews::DeleteRange(const ui::Range& range) { } bool NativeTextfieldViews::GetTextFromRange( - const ui::Range& range, + const gfx::Range& range, string16* text) { if (!ImeEditingAllowed() || !range.IsValid()) return false; - ui::Range text_range; + gfx::Range text_range; if (!GetTextRange(&text_range) || !text_range.Contains(range)) return false; @@ -1086,12 +1098,12 @@ bool NativeTextfieldViews::ChangeTextDirectionAndLayoutAlignment( void NativeTextfieldViews::ExtendSelectionAndDelete( size_t before, size_t after) { - ui::Range range = GetSelectedRange(); + gfx::Range range = GetSelectedRange(); DCHECK_GE(range.start(), before); range.set_start(range.start() - before); range.set_end(range.end() + after); - ui::Range text_range; + gfx::Range text_range; if (GetTextRange(&text_range) && text_range.Contains(range)) DeleteRange(range); } @@ -1178,7 +1190,7 @@ bool NativeTextfieldViews::HandleKeyEvent(const ui::KeyEvent& key_event) { const bool readable = !textfield_->IsObscured(); const bool shift = key_event.IsShiftDown(); const bool control = key_event.IsControlDown(); - const bool alt = key_event.IsAltDown(); + const bool alt = key_event.IsAltDown() || key_event.IsAltGrDown(); bool text_changed = false; bool cursor_changed = false; switch (key_code) { @@ -1217,7 +1229,7 @@ bool NativeTextfieldViews::HandleKeyEvent(const ui::KeyEvent& key_event) { // forward/back of the browser history. if (alt) break; - const ui::Range selection_range = GetSelectedRange(); + const gfx::Range selection_range = GetSelectedRange(); model_->MoveCursor( control ? gfx::WORD_BREAK : gfx::CHARACTER_BREAK, (key_code == ui::VKEY_RIGHT) ? gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT, @@ -1322,6 +1334,8 @@ void NativeTextfieldViews::UpdateAfterChange(bool text_changed, void NativeTextfieldViews::UpdateContextMenu() { if (!context_menu_contents_.get()) { context_menu_contents_.reset(new ui::SimpleMenuModel(this)); + context_menu_contents_->AddItemWithStringId(IDS_APP_UNDO, IDS_APP_UNDO); + context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR); context_menu_contents_->AddItemWithStringId(IDS_APP_CUT, IDS_APP_CUT); context_menu_contents_->AddItemWithStringId(IDS_APP_COPY, IDS_APP_COPY); context_menu_contents_->AddItemWithStringId(IDS_APP_PASTE, IDS_APP_PASTE); diff --git a/chromium/ui/views/controls/textfield/native_textfield_views.h b/chromium/ui/views/controls/textfield/native_textfield_views.h index 3230fb4d6c8..6b1c2de3724 100644 --- a/chromium/ui/views/controls/textfield/native_textfield_views.h +++ b/chromium/ui/views/controls/textfield/native_textfield_views.h @@ -8,10 +8,10 @@ #include "base/memory/weak_ptr.h" #include "base/strings/string16.h" #include "base/timer/timer.h" -#include "ui/base/events/event_constants.h" #include "ui/base/ime/text_input_client.h" #include "ui/base/models/simple_menu_model.h" #include "ui/base/touch/touch_editing_controller.h" +#include "ui/events/event_constants.h" #include "ui/gfx/font.h" #include "ui/views/border.h" #include "ui/views/context_menu_controller.h" @@ -130,8 +130,8 @@ class VIEWS_EXPORT NativeTextfieldViews : public View, virtual View* GetView() OVERRIDE; virtual gfx::NativeView GetTestingHandle() const OVERRIDE; virtual bool IsIMEComposing() const OVERRIDE; - virtual ui::Range GetSelectedRange() const OVERRIDE; - virtual void SelectRange(const ui::Range& range) OVERRIDE; + virtual gfx::Range GetSelectedRange() const OVERRIDE; + virtual void SelectRange(const gfx::Range& range) OVERRIDE; virtual gfx::SelectionModel GetSelectionModel() const OVERRIDE; virtual void SelectSelectionModel(const gfx::SelectionModel& sel) OVERRIDE; virtual size_t GetCursorPosition() const OVERRIDE; @@ -143,17 +143,18 @@ class VIEWS_EXPORT NativeTextfieldViews : public View, virtual void HandleBlur() OVERRIDE; virtual ui::TextInputClient* GetTextInputClient() OVERRIDE; virtual void SetColor(SkColor value) OVERRIDE; - virtual void ApplyColor(SkColor value, const ui::Range& range) OVERRIDE; + virtual void ApplyColor(SkColor value, const gfx::Range& range) OVERRIDE; virtual void SetStyle(gfx::TextStyle style, bool value) OVERRIDE; virtual void ApplyStyle(gfx::TextStyle style, bool value, - const ui::Range& range) OVERRIDE; + const gfx::Range& range) OVERRIDE; virtual void ClearEditHistory() OVERRIDE; virtual int GetFontHeight() OVERRIDE; virtual int GetTextfieldBaseline() const OVERRIDE; virtual int GetWidthNeededForText() const OVERRIDE; virtual void ExecuteTextCommand(int command_id) OVERRIDE; virtual bool HasTextBeingDragged() OVERRIDE; + virtual gfx::Point GetContextMenuLocation() OVERRIDE; // ui::SimpleMenuModel::Delegate overrides virtual bool IsCommandIdChecked(int command_id) const OVERRIDE; @@ -191,12 +192,12 @@ class VIEWS_EXPORT NativeTextfieldViews : public View, virtual bool GetCompositionCharacterBounds(uint32 index, gfx::Rect* rect) OVERRIDE; virtual bool HasCompositionText() OVERRIDE; - virtual bool GetTextRange(ui::Range* range) OVERRIDE; - virtual bool GetCompositionTextRange(ui::Range* range) OVERRIDE; - virtual bool GetSelectionRange(ui::Range* range) OVERRIDE; - virtual bool SetSelectionRange(const ui::Range& range) OVERRIDE; - virtual bool DeleteRange(const ui::Range& range) OVERRIDE; - virtual bool GetTextFromRange(const ui::Range& range, + virtual bool GetTextRange(gfx::Range* range) OVERRIDE; + virtual bool GetCompositionTextRange(gfx::Range* range) OVERRIDE; + virtual bool GetSelectionRange(gfx::Range* range) OVERRIDE; + virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE; + virtual bool DeleteRange(const gfx::Range& range) OVERRIDE; + virtual bool GetTextFromRange(const gfx::Range& range, string16* text) OVERRIDE; virtual void OnInputMethodChanged() OVERRIDE; virtual bool ChangeTextDirectionAndLayoutAlignment( @@ -325,7 +326,7 @@ class VIEWS_EXPORT NativeTextfieldViews : public View, size_t aggregated_clicks_; base::TimeDelta last_click_time_; gfx::Point last_click_location_; - ui::Range double_click_word_; + gfx::Range double_click_word_; // Context menu and its content list for the textfield. scoped_ptr<ui::SimpleMenuModel> context_menu_contents_; diff --git a/chromium/ui/views/controls/textfield/native_textfield_views_unittest.cc b/chromium/ui/views/controls/textfield/native_textfield_views_unittest.cc index c2e32c998a4..54873d95b64 100644 --- a/chromium/ui/views/controls/textfield/native_textfield_views_unittest.cc +++ b/chromium/ui/views/controls/textfield/native_textfield_views_unittest.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "ui/views/controls/textfield/native_textfield_views.h" + #include <set> #include <string> #include <vector> @@ -20,13 +22,12 @@ #include "ui/base/clipboard/clipboard.h" #include "ui/base/clipboard/scoped_clipboard_writer.h" #include "ui/base/dragdrop/drag_drop_types.h" -#include "ui/base/events/event.h" #include "ui/base/ime/text_input_client.h" -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/ui_base_switches.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/render_text.h" -#include "ui/views/controls/textfield/native_textfield_views.h" #include "ui/views/controls/textfield/textfield.h" #include "ui/views/controls/textfield/textfield_controller.h" #include "ui/views/controls/textfield/textfield_views_model.h" @@ -38,6 +39,10 @@ #include "ui/views/widget/widget.h" #include "url/gurl.h" +#if defined(OS_WIN) +#include "base/win/windows_version.h" +#endif + #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16) namespace { @@ -179,6 +184,7 @@ class NativeTextfieldViewsTest : public ViewsTestBase, textfield_view_ = static_cast<NativeTextfieldViews*>( textfield_->GetNativeWrapperForTesting()); + DCHECK(textfield_view_); textfield_view_->SetBoundsRect(params.bounds); textfield_->set_id(1); @@ -188,7 +194,6 @@ class NativeTextfieldViewsTest : public ViewsTestBase, textfield->set_id(i + 1); } - DCHECK(textfield_view_); model_ = textfield_view_->model_.get(); model_->ClearEditHistory(); @@ -314,14 +319,16 @@ class NativeTextfieldViewsTest : public ViewsTestBase, } void VerifyTextfieldContextMenuContents(bool textfield_has_selection, - ui::MenuModel* menu_model) { - EXPECT_TRUE(menu_model->IsEnabledAt(4 /* Separator */)); - EXPECT_TRUE(menu_model->IsEnabledAt(5 /* SELECT ALL */)); - EXPECT_EQ(textfield_has_selection, menu_model->IsEnabledAt(0 /* CUT */)); - EXPECT_EQ(textfield_has_selection, menu_model->IsEnabledAt(1 /* COPY */)); - EXPECT_EQ(textfield_has_selection, menu_model->IsEnabledAt(3 /* DELETE */)); - string16 str(GetClipboardText()); - EXPECT_NE(str.empty(), menu_model->IsEnabledAt(2 /* PASTE */)); + bool can_undo, + ui::MenuModel* menu) { + EXPECT_EQ(can_undo, menu->IsEnabledAt(0 /* UNDO */)); + EXPECT_TRUE(menu->IsEnabledAt(1 /* Separator */)); + EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(2 /* CUT */)); + EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(3 /* COPY */)); + EXPECT_NE(GetClipboardText().empty(), menu->IsEnabledAt(4 /* PASTE */)); + EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(5 /* DELETE */)); + EXPECT_TRUE(menu->IsEnabledAt(6 /* Separator */)); + EXPECT_TRUE(menu->IsEnabledAt(7 /* SELECT ALL */)); } // We need widget to populate wrapper class. @@ -505,7 +512,7 @@ TEST_F(NativeTextfieldViewsTest, InsertionDeletionTest) { EXPECT_STR_EQ("abcdefghij", textfield_->text()); // Test the delete and backspace keys. - textfield_->SelectRange(ui::Range(5)); + textfield_->SelectRange(gfx::Range(5)); for (int i = 0; i < 3; i++) SendKeyEvent(ui::VKEY_BACK); EXPECT_STR_EQ("abfghij", textfield_->text()); @@ -786,11 +793,23 @@ TEST_F(NativeTextfieldViewsTest, ContextMenuDisplayTest) { InitTextfield(Textfield::STYLE_DEFAULT); EXPECT_TRUE(textfield_->context_menu_controller()); textfield_->SetText(ASCIIToUTF16("hello world")); + ui::Clipboard::GetForCurrentThread()->Clear(ui::Clipboard::BUFFER_STANDARD); + textfield_view_->ClearEditHistory(); EXPECT_TRUE(GetContextMenuModel()); - VerifyTextfieldContextMenuContents(false, GetContextMenuModel()); + VerifyTextfieldContextMenuContents(false, false, GetContextMenuModel()); + + textfield_->SelectAll(false); + VerifyTextfieldContextMenuContents(true, false, GetContextMenuModel()); + + SendKeyEvent(ui::VKEY_T); + VerifyTextfieldContextMenuContents(false, true, GetContextMenuModel()); textfield_->SelectAll(false); - VerifyTextfieldContextMenuContents(true, GetContextMenuModel()); + VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel()); + + // Exercise the "paste enabled?" check in the verifier. + SetClipboardText("Test"); + VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel()); } TEST_F(NativeTextfieldViewsTest, DoubleAndTripleClickTest) { @@ -922,7 +941,7 @@ TEST_F(NativeTextfieldViewsTest, DragAndDrop_InitiateDrag) { // Ensure the textfield will provide selected text for drag data. string16 string; ui::OSExchangeData data; - const ui::Range kStringRange(6, 12); + const gfx::Range kStringRange(6, 12); textfield_->SelectRange(kStringRange); const gfx::Point kStringPoint(GetCursorPositionX(9), 0); textfield_view_->WriteDragDataForView(NULL, kStringPoint, &data); @@ -972,7 +991,7 @@ TEST_F(NativeTextfieldViewsTest, DragAndDrop_ToTheRight) { std::set<OSExchangeData::CustomFormat> custom_formats; // Start dragging "ello". - textfield_->SelectRange(ui::Range(1, 5)); + textfield_->SelectRange(gfx::Range(1, 5)); gfx::Point point(GetCursorPositionX(3), 0); ui::MouseEvent click_a(ui::ET_MOUSE_PRESSED, point, point, ui::EF_LEFT_MOUSE_BUTTON); @@ -1027,7 +1046,7 @@ TEST_F(NativeTextfieldViewsTest, DragAndDrop_ToTheLeft) { std::set<OSExchangeData::CustomFormat> custom_formats; // Start dragging " worl". - textfield_->SelectRange(ui::Range(5, 10)); + textfield_->SelectRange(gfx::Range(5, 10)); gfx::Point point(GetCursorPositionX(7), 0); ui::MouseEvent click_a(ui::ET_MOUSE_PRESSED, point, point, ui::EF_LEFT_MOUSE_BUTTON); @@ -1076,7 +1095,7 @@ TEST_F(NativeTextfieldViewsTest, DragAndDrop_Canceled) { textfield_->SetText(ASCIIToUTF16("hello world")); // Start dragging "worl". - textfield_->SelectRange(ui::Range(6, 10)); + textfield_->SelectRange(gfx::Range(6, 10)); gfx::Point point(GetCursorPositionX(8), 0); ui::MouseEvent click(ui::ET_MOUSE_PRESSED, point, point, ui::EF_LEFT_MOUSE_BUTTON); @@ -1174,14 +1193,14 @@ TEST_F(NativeTextfieldViewsTest, TextInputClientTest) { EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, client->GetTextInputType()); textfield_->SetText(ASCIIToUTF16("0123456789")); - ui::Range range; + gfx::Range range; EXPECT_TRUE(client->GetTextRange(&range)); EXPECT_EQ(0U, range.start()); EXPECT_EQ(10U, range.end()); - EXPECT_TRUE(client->SetSelectionRange(ui::Range(1, 4))); + EXPECT_TRUE(client->SetSelectionRange(gfx::Range(1, 4))); EXPECT_TRUE(client->GetSelectionRange(&range)); - EXPECT_EQ(ui::Range(1, 4), range); + EXPECT_EQ(gfx::Range(1, 4), range); // This code can't be compiled because of a bug in base::Callback. #if 0 @@ -1210,7 +1229,7 @@ TEST_F(NativeTextfieldViewsTest, TextInputClientTest) { EXPECT_TRUE(client->HasCompositionText()); EXPECT_TRUE(client->GetCompositionTextRange(&range)); EXPECT_STR_EQ("0321456789", textfield_->text()); - EXPECT_EQ(ui::Range(1, 4), range); + EXPECT_EQ(gfx::Range(1, 4), range); EXPECT_EQ(2, on_before_user_action_); EXPECT_EQ(2, on_after_user_action_); @@ -1247,7 +1266,7 @@ TEST_F(NativeTextfieldViewsTest, TextInputClientTest) { textfield_->clear(); textfield_->SetText(ASCIIToUTF16("0123456789")); - EXPECT_TRUE(client->SetSelectionRange(ui::Range(5, 5))); + EXPECT_TRUE(client->SetSelectionRange(gfx::Range(5, 5))); client->ExtendSelectionAndDelete(4, 2); EXPECT_STR_EQ("0789", textfield_->text()); @@ -1755,7 +1774,7 @@ TEST_F(NativeTextfieldViewsTest, GetCompositionCharacterBoundsTest) { gfx::Rect char_rect_in_screen_coord[char_count]; gfx::Rect prev_cursor = GetCursorBounds(); for (uint32 i = 0; i < char_count; ++i) { - composition.selection = ui::Range(0, i+1); + composition.selection = gfx::Range(0, i+1); client->SetCompositionText(composition); EXPECT_TRUE(client->HasCompositionText()) << " i=" << i; gfx::Rect cursor_bounds = GetCursorBounds(); @@ -1789,9 +1808,9 @@ TEST_F(NativeTextfieldViewsTest, KeepInitiallySelectedWord) { textfield_->SetText(ASCIIToUTF16("abc def ghi")); - textfield_->SelectRange(ui::Range(5, 5)); + textfield_->SelectRange(gfx::Range(5, 5)); const gfx::Rect middle_cursor = GetCursorBounds(); - textfield_->SelectRange(ui::Range(0, 0)); + textfield_->SelectRange(gfx::Range(0, 0)); const gfx::Point beginning = GetCursorBounds().origin(); // Double click, but do not release the left button. @@ -1801,13 +1820,13 @@ TEST_F(NativeTextfieldViewsTest, KeepInitiallySelectedWord) { ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, middle, middle, ui::EF_LEFT_MOUSE_BUTTON); textfield_view_->OnMousePressed(press_event); - EXPECT_EQ(ui::Range(4, 7), textfield_->GetSelectedRange()); + EXPECT_EQ(gfx::Range(4, 7), textfield_->GetSelectedRange()); // Drag the mouse to the beginning of the textfield. ui::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, beginning, beginning, ui::EF_LEFT_MOUSE_BUTTON); textfield_view_->OnMouseDragged(drag_event); - EXPECT_EQ(ui::Range(7, 0), textfield_->GetSelectedRange()); + EXPECT_EQ(gfx::Range(7, 0), textfield_->GetSelectedRange()); } // Touch selection and draggin currently only works for chromeos. @@ -1868,7 +1887,7 @@ TEST_F(NativeTextfieldViewsTest, TestLongPressInitiatesDragDrop) { textfield_->SetText(ASCIIToUTF16("Hello string world")); // Ensure the textfield will provide selected text for drag data. - textfield_->SelectRange(ui::Range(6, 12)); + textfield_->SelectRange(gfx::Range(6, 12)); const gfx::Point kStringPoint(GetCursorPositionX(9), 0); // Enable touch-drag-drop to make long press effective. @@ -1882,4 +1901,26 @@ TEST_F(NativeTextfieldViewsTest, TestLongPressInitiatesDragDrop) { EXPECT_TRUE(textfield_view_->CanStartDragForView(NULL, kStringPoint, kStringPoint)); } + +TEST_F(NativeTextfieldViewsTest, GetTextfieldBaseline_FontFallbackTest) { +#if defined(OS_WIN) + // This test fails on some versions of Windows because two different strings + // have the same baseline. + if (base::win::GetVersion() <= base::win::VERSION_XP || + base::win::VERSION_WIN8 <= base::win::GetVersion()) + return; +#endif + + InitTextfield(Textfield::STYLE_DEFAULT); + textfield_->SetText(UTF8ToUTF16("abc")); + const int old_baseline = textfield_->GetBaseline(); + + // Set text which may fall back to a font which has taller baseline than + // the default font. |new_baseline| will be greater than |old_baseline|. + textfield_->SetText(UTF8ToUTF16("\xE0\xB9\x91")); + const int new_baseline = textfield_->GetBaseline(); + + EXPECT_GT(new_baseline, old_baseline); +} + } // namespace views diff --git a/chromium/ui/views/controls/textfield/native_textfield_win.cc b/chromium/ui/views/controls/textfield/native_textfield_win.cc index defe632cf80..f98c0ad75d2 100644 --- a/chromium/ui/views/controls/textfield/native_textfield_win.cc +++ b/chromium/ui/views/controls/textfield/native_textfield_win.cc @@ -17,14 +17,14 @@ #include "ui/base/accessibility/accessible_view_state.h" #include "ui/base/clipboard/clipboard.h" #include "ui/base/clipboard/scoped_clipboard_writer.h" -#include "ui/base/events/event.h" #include "ui/base/ime/win/tsf_bridge.h" -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util_win.h" -#include "ui/base/range/range.h" -#include "ui/base/win/hwnd_util.h" #include "ui/base/win/mouse_wheel_util.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/keyboard_codes.h" +#include "ui/gfx/range/range.h" +#include "ui/gfx/win/hwnd_util.h" #include "ui/native_theme/native_theme_win.h" #include "ui/views/controls/label.h" #include "ui/views/controls/menu/menu_item_view.h" @@ -340,13 +340,13 @@ bool NativeTextfieldWin::IsIMEComposing() const { return composition_size > 0; } -ui::Range NativeTextfieldWin::GetSelectedRange() const { +gfx::Range NativeTextfieldWin::GetSelectedRange() const { // TODO(tommi): Implement. NOTIMPLEMENTED(); - return ui::Range(); + return gfx::Range(); } -void NativeTextfieldWin::SelectRange(const ui::Range& range) { +void NativeTextfieldWin::SelectRange(const gfx::Range& range) { // TODO(tommi): Implement. NOTIMPLEMENTED(); } @@ -401,7 +401,7 @@ void NativeTextfieldWin::SetColor(SkColor value) { NOTREACHED(); } -void NativeTextfieldWin::ApplyColor(SkColor value, const ui::Range& range) { +void NativeTextfieldWin::ApplyColor(SkColor value, const gfx::Range& range) { NOTREACHED(); } @@ -411,7 +411,7 @@ void NativeTextfieldWin::SetStyle(gfx::TextStyle style, bool value) { void NativeTextfieldWin::ApplyStyle(gfx::TextStyle style, bool value, - const ui::Range& range) { + const gfx::Range& range) { NOTREACHED(); } @@ -441,6 +441,11 @@ bool NativeTextfieldWin::HasTextBeingDragged() { return false; } +gfx::Point NativeTextfieldWin::GetContextMenuLocation() { + NOTIMPLEMENTED(); + return gfx::Point(); +} + //////////////////////////////////////////////////////////////////////////////// // NativeTextfieldWin, ui::SimpleMenuModel::Delegate implementation: @@ -493,7 +498,7 @@ void NativeTextfieldWin::ExecuteCommand(int command_id, int event_flags) { OnAfterPossibleChange(true); } -void NativeTextfieldWin::OnTextUpdated(const ui::Range& composition_range) { +void NativeTextfieldWin::OnTextUpdated(const gfx::Range& composition_range) { if (ime_discard_composition_) { ime_composition_start_ = composition_range.start(); ime_composition_length_ = composition_range.length(); @@ -1103,7 +1108,7 @@ void NativeTextfieldWin::OnSysChar(TCHAR ch, UINT repeat_count, UINT flags) { // something useful, so discard those. Note that [Ctrl]+[Alt]+<xxx> generates // WM_CHAR instead of WM_SYSCHAR, so it is not handled here. if (ch == VK_SPACE) { - ui::ShowSystemMenu( + gfx::ShowSystemMenu( container_view_->GetWidget()->GetTopLevelWidget()->GetNativeWindow()); } } diff --git a/chromium/ui/views/controls/textfield/native_textfield_win.h b/chromium/ui/views/controls/textfield/native_textfield_win.h index 6e119b11a60..6939a093f32 100644 --- a/chromium/ui/views/controls/textfield/native_textfield_win.h +++ b/chromium/ui/views/controls/textfield/native_textfield_win.h @@ -21,6 +21,7 @@ #include "ui/base/models/simple_menu_model.h" #include "ui/base/win/extra_sdk_defines.h" #include "ui/gfx/insets.h" +#include "ui/gfx/point.h" #include "ui/views/controls/textfield/native_textfield_wrapper.h" namespace views { @@ -79,8 +80,8 @@ class NativeTextfieldWin virtual View* GetView() OVERRIDE; virtual gfx::NativeView GetTestingHandle() const OVERRIDE; virtual bool IsIMEComposing() const OVERRIDE; - virtual ui::Range GetSelectedRange() const OVERRIDE; - virtual void SelectRange(const ui::Range& range) OVERRIDE; + virtual gfx::Range GetSelectedRange() const OVERRIDE; + virtual void SelectRange(const gfx::Range& range) OVERRIDE; virtual gfx::SelectionModel GetSelectionModel() const OVERRIDE; virtual void SelectSelectionModel(const gfx::SelectionModel& sel) OVERRIDE; virtual size_t GetCursorPosition() const OVERRIDE; @@ -92,17 +93,18 @@ class NativeTextfieldWin virtual void HandleBlur() OVERRIDE; virtual ui::TextInputClient* GetTextInputClient() OVERRIDE; virtual void SetColor(SkColor value) OVERRIDE; - virtual void ApplyColor(SkColor value, const ui::Range& range) OVERRIDE; + virtual void ApplyColor(SkColor value, const gfx::Range& range) OVERRIDE; virtual void SetStyle(gfx::TextStyle style, bool value) OVERRIDE; virtual void ApplyStyle(gfx::TextStyle style, bool value, - const ui::Range& range) OVERRIDE; + const gfx::Range& range) OVERRIDE; virtual void ClearEditHistory() OVERRIDE; virtual int GetFontHeight() OVERRIDE; virtual int GetTextfieldBaseline() const OVERRIDE; virtual int GetWidthNeededForText() const OVERRIDE; virtual void ExecuteTextCommand(int command_id) OVERRIDE; virtual bool HasTextBeingDragged() OVERRIDE; + virtual gfx::Point GetContextMenuLocation() OVERRIDE; // ui::SimpleMenuModel::Delegate: virtual bool IsCommandIdChecked(int command_id) const OVERRIDE; @@ -113,7 +115,7 @@ class NativeTextfieldWin virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE; // ui::TSFEventRouterObserver: - virtual void OnTextUpdated(const ui::Range& composition_range) OVERRIDE; + virtual void OnTextUpdated(const gfx::Range& composition_range) OVERRIDE; virtual void OnTSFStartComposition() OVERRIDE; virtual void OnTSFEndComposition() OVERRIDE; diff --git a/chromium/ui/views/controls/textfield/native_textfield_wrapper.h b/chromium/ui/views/controls/textfield/native_textfield_wrapper.h index 82e75b381b9..3d8938e3286 100644 --- a/chromium/ui/views/controls/textfield/native_textfield_wrapper.h +++ b/chromium/ui/views/controls/textfield/native_textfield_wrapper.h @@ -7,14 +7,15 @@ #include "base/i18n/rtl.h" #include "base/strings/string16.h" -#include "ui/base/range/range.h" #include "ui/gfx/native_widget_types.h" +#include "ui/gfx/range/range.h" #include "ui/gfx/selection_model.h" #include "ui/gfx/text_constants.h" #include "ui/views/views_export.h" namespace gfx { class Insets; +class Point; } // namespace gfx namespace ui { @@ -109,10 +110,10 @@ class VIEWS_EXPORT NativeTextfieldWrapper { virtual bool IsIMEComposing() const = 0; // Gets the selected range. - virtual ui::Range GetSelectedRange() const = 0; + virtual gfx::Range GetSelectedRange() const = 0; // Selects the text given by |range|. - virtual void SelectRange(const ui::Range& range) = 0; + virtual void SelectRange(const gfx::Range& range) = 0; // Gets the selection model. virtual gfx::SelectionModel GetSelectionModel() const = 0; @@ -149,13 +150,13 @@ class VIEWS_EXPORT NativeTextfieldWrapper { // Set the text colors; see the corresponding Textfield functions for details. virtual void SetColor(SkColor value) = 0; - virtual void ApplyColor(SkColor value, const ui::Range& range) = 0; + virtual void ApplyColor(SkColor value, const gfx::Range& range) = 0; // Set the text styles; see the corresponding Textfield functions for details. virtual void SetStyle(gfx::TextStyle style, bool value) = 0; virtual void ApplyStyle(gfx::TextStyle style, bool value, - const ui::Range& range) = 0; + const gfx::Range& range) = 0; // Clears Edit history. virtual void ClearEditHistory() = 0; @@ -178,6 +179,9 @@ class VIEWS_EXPORT NativeTextfieldWrapper { // Returns whether there is a drag operation originating from the textfield. virtual bool HasTextBeingDragged() = 0; + // Returns the location for keyboard-triggered context menus. + virtual gfx::Point GetContextMenuLocation() = 0; + // Creates an appropriate NativeTextfieldWrapper for the platform. static NativeTextfieldWrapper* CreateWrapper(Textfield* field); }; diff --git a/chromium/ui/views/controls/textfield/textfield.cc b/chromium/ui/views/controls/textfield/textfield.cc index b76c20c8ac8..b26aa37120a 100644 --- a/chromium/ui/views/controls/textfield/textfield.cc +++ b/chromium/ui/views/controls/textfield/textfield.cc @@ -10,14 +10,13 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "ui/base/accessibility/accessible_view_state.h" -#include "ui/base/events/event.h" #include "ui/base/ime/text_input_type.h" -#include "ui/base/keycodes/keyboard_codes.h" -#include "ui/base/range/range.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_base_switches.h" -#include "ui/base/ui_base_switches_util.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/insets.h" +#include "ui/gfx/range/range.h" #include "ui/gfx/selection_model.h" #include "ui/native_theme/native_theme.h" #include "ui/views/controls/native/native_view_host.h" @@ -62,9 +61,6 @@ bool Textfield::IsViewsTextfieldEnabled() { return false; if (command_line->HasSwitch(switches::kEnableViewsTextfield)) return true; - // The new dialog style cannot host native Windows textfield controls. - if (switches::IsNewDialogStyleEnabled()) - return true; // Avoid native Windows Textfields if the RichEdit library is not available. static const HMODULE loaded_msftedit_dll = LoadLibrary(L"msftedit.dll"); if (!loaded_msftedit_dll) @@ -367,11 +363,11 @@ bool Textfield::IsIMEComposing() const { return native_wrapper_ && native_wrapper_->IsIMEComposing(); } -ui::Range Textfield::GetSelectedRange() const { +gfx::Range Textfield::GetSelectedRange() const { return native_wrapper_->GetSelectedRange(); } -void Textfield::SelectRange(const ui::Range& range) { +void Textfield::SelectRange(const gfx::Range& range) { native_wrapper_->SelectRange(range); } @@ -391,7 +387,7 @@ void Textfield::SetColor(SkColor value) { return native_wrapper_->SetColor(value); } -void Textfield::ApplyColor(SkColor value, const ui::Range& range) { +void Textfield::ApplyColor(SkColor value, const gfx::Range& range) { return native_wrapper_->ApplyColor(value, range); } @@ -401,7 +397,7 @@ void Textfield::SetStyle(gfx::TextStyle style, bool value) { void Textfield::ApplyStyle(gfx::TextStyle style, bool value, - const ui::Range& range) { + const gfx::Range& range) { return native_wrapper_->ApplyStyle(style, value, range); } @@ -505,7 +501,7 @@ void Textfield::GetAccessibleState(ui::AccessibleViewState* state) { state->state |= ui::AccessibilityTypes::STATE_PROTECTED; state->value = text_; - const ui::Range range = native_wrapper_->GetSelectedRange(); + const gfx::Range range = native_wrapper_->GetSelectedRange(); state->selection_start = range.start(); state->selection_end = range.end(); @@ -520,6 +516,11 @@ ui::TextInputClient* Textfield::GetTextInputClient() { return native_wrapper_ ? native_wrapper_->GetTextInputClient() : NULL; } +gfx::Point Textfield::GetKeyboardContextMenuLocation() { + return native_wrapper_ ? native_wrapper_->GetContextMenuLocation() : + View::GetKeyboardContextMenuLocation(); +} + void Textfield::OnEnabledChanged() { View::OnEnabledChanged(); if (native_wrapper_) diff --git a/chromium/ui/views/controls/textfield/textfield.h b/chromium/ui/views/controls/textfield/textfield.h index 71b663bd2e5..3f796357b0d 100644 --- a/chromium/ui/views/controls/textfield/textfield.h +++ b/chromium/ui/views/controls/textfield/textfield.h @@ -15,7 +15,7 @@ #include "build/build_config.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/base/ime/text_input_type.h" -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/font_list.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/text_constants.h" @@ -27,11 +27,11 @@ #endif namespace gfx { +class Range; class ImageSkia; } namespace ui { -class Range; class TextInputClient; } // namespace ui @@ -172,9 +172,6 @@ class VIEWS_EXPORT Textfield : public View { // Sets the text to display when empty. void set_placeholder_text(const string16& text) { placeholder_text_ = text; -#if !defined(OS_LINUX) - NOTIMPLEMENTED(); -#endif } const string16& placeholder_text() const { return placeholder_text_; @@ -209,11 +206,11 @@ class VIEWS_EXPORT Textfield : public View { // Gets the selected range. This is views-implementation only and // has to be called after the wrapper is created. // TODO(msw): Return a const reference when NativeTextfieldWin is gone. - ui::Range GetSelectedRange() const; + gfx::Range GetSelectedRange() const; // Selects the text given by |range|. This is views-implementation only and // has to be called after the wrapper is created. - void SelectRange(const ui::Range& range); + void SelectRange(const gfx::Range& range); // Gets the selection model. This is views-implementation only and // has to be called after the wrapper is created. @@ -232,14 +229,14 @@ class VIEWS_EXPORT Textfield : public View { // Empty and invalid ranges are ignored. This is views-implementation only and // has to be called after the wrapper is created. void SetColor(SkColor value); - void ApplyColor(SkColor value, const ui::Range& range); + void ApplyColor(SkColor value, const gfx::Range& range); // Set various text styles over the entire text or a logical character range. // The respective |style| is applied if |value| is true, or removed if false. // Empty and invalid ranges are ignored. This is views-implementation only and // has to be called after the wrapper is created. void SetStyle(gfx::TextStyle style, bool value); - void ApplyStyle(gfx::TextStyle style, bool value, const ui::Range& range); + void ApplyStyle(gfx::TextStyle style, bool value, const gfx::Range& range); // Clears Edit history. void ClearEditHistory(); @@ -276,6 +273,7 @@ class VIEWS_EXPORT Textfield : public View { virtual void OnBlur() OVERRIDE; virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; virtual ui::TextInputClient* GetTextInputClient() OVERRIDE; + virtual gfx::Point GetKeyboardContextMenuLocation() OVERRIDE; protected: virtual void ViewHierarchyChanged( diff --git a/chromium/ui/views/controls/textfield/textfield_controller.cc b/chromium/ui/views/controls/textfield/textfield_controller.cc index d9899d2e59a..8f72be8a1c4 100644 --- a/chromium/ui/views/controls/textfield/textfield_controller.cc +++ b/chromium/ui/views/controls/textfield/textfield_controller.cc @@ -5,7 +5,7 @@ #include "ui/views/controls/textfield/textfield_controller.h" #include "ui/base/dragdrop/drag_drop_types.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" namespace views { diff --git a/chromium/ui/views/controls/textfield/textfield_views_model.cc b/chromium/ui/views/controls/textfield/textfield_views_model.cc index 5ff20a5422a..dae5684889c 100644 --- a/chromium/ui/views/controls/textfield/textfield_views_model.cc +++ b/chromium/ui/views/controls/textfield/textfield_views_model.cc @@ -12,12 +12,12 @@ #include "base/strings/utf_string_conversions.h" #include "ui/base/clipboard/clipboard.h" #include "ui/base/clipboard/scoped_clipboard_writer.h" -#include "ui/base/range/range.h" -#include "ui/base/text/utf16_indexing.h" #include "ui/gfx/canvas.h" #include "ui/gfx/font.h" +#include "ui/gfx/range/range.h" #include "ui/gfx/render_text.h" #include "ui/gfx/text_constants.h" +#include "ui/gfx/utf16_indexing.h" #include "ui/views/controls/textfield/textfield.h" namespace views { @@ -269,13 +269,13 @@ namespace { // Returns the first segment that is visually emphasized. Usually it's used for // representing the target clause (on Windows). Returns an invalid range if // there is no such a range. -ui::Range GetFirstEmphasizedRange(const ui::CompositionText& composition) { +gfx::Range GetFirstEmphasizedRange(const ui::CompositionText& composition) { for (size_t i = 0; i < composition.underlines.size(); ++i) { const ui::CompositionUnderline& underline = composition.underlines[i]; if (underline.thick) - return ui::Range(underline.start_offset, underline.end_offset); + return gfx::Range(underline.start_offset, underline.end_offset); } - return ui::Range::InvalidRange(); + return gfx::Range::InvalidRange(); } } // namespace @@ -363,7 +363,7 @@ bool TextfieldViewsModel::Delete() { size_t cursor_position = GetCursorPosition(); size_t next_grapheme_index = render_text_->IndexOfAdjacentGrapheme( cursor_position, gfx::CURSOR_FORWARD); - ExecuteAndRecordDelete(ui::Range(cursor_position, next_grapheme_index), + ExecuteAndRecordDelete(gfx::Range(cursor_position, next_grapheme_index), true); return true; } @@ -384,8 +384,8 @@ bool TextfieldViewsModel::Backspace() { if (cursor_position > 0) { // Delete one code point, which may be two UTF-16 words. size_t previous_char = - ui::UTF16OffsetToIndex(GetText(), cursor_position, -1); - ExecuteAndRecordDelete(ui::Range(cursor_position, previous_char), true); + gfx::UTF16OffsetToIndex(GetText(), cursor_position, -1); + ExecuteAndRecordDelete(gfx::Range(cursor_position, previous_char), true); return true; } return false; @@ -408,7 +408,7 @@ bool TextfieldViewsModel::MoveCursorTo(const gfx::SelectionModel& model) { ConfirmCompositionText(); // ConfirmCompositionText() updates cursor position. Need to reflect it in // the SelectionModel parameter of MoveCursorTo(). - ui::Range range(render_text_->selection().start(), model.caret_pos()); + gfx::Range range(render_text_->selection().start(), model.caret_pos()); if (!range.is_empty()) return render_text_->SelectRange(range); return render_text_->MoveCursorTo( @@ -428,7 +428,7 @@ string16 TextfieldViewsModel::GetSelectedText() const { render_text_->selection().length()); } -void TextfieldViewsModel::SelectRange(const ui::Range& range) { +void TextfieldViewsModel::SelectRange(const gfx::Range& range) { if (HasCompositionText()) ConfirmCompositionText(); render_text_->SelectRange(range); @@ -518,8 +518,8 @@ bool TextfieldViewsModel::Cut() { // than beginning, unlike Delete/Backspace. // TODO(oshima): Change Delete/Backspace to use DeleteSelection, // update DeleteEdit and remove this trick. - const ui::Range& selection = render_text_->selection(); - render_text_->SelectRange(ui::Range(selection.end(), selection.start())); + const gfx::Range& selection = render_text_->selection(); + render_text_->SelectRange(gfx::Range(selection.end(), selection.start())); DeleteSelection(); return true; } @@ -568,14 +568,14 @@ void TextfieldViewsModel::DeleteSelectionAndInsertTextAt( position); } -string16 TextfieldViewsModel::GetTextFromRange(const ui::Range& range) const { +string16 TextfieldViewsModel::GetTextFromRange(const gfx::Range& range) const { if (range.IsValid() && range.GetMin() < GetText().length()) return GetText().substr(range.GetMin(), range.length()); return string16(); } -void TextfieldViewsModel::GetTextRange(ui::Range* range) const { - *range = ui::Range(0, GetText().length()); +void TextfieldViewsModel::GetTextRange(gfx::Range* range) const { + *range = gfx::Range(0, GetText().length()); } void TextfieldViewsModel::SetCompositionText( @@ -591,9 +591,9 @@ void TextfieldViewsModel::SetCompositionText( size_t cursor = GetCursorPosition(); string16 new_text = GetText(); render_text_->SetText(new_text.insert(cursor, composition.text)); - ui::Range range(cursor, cursor + composition.text.length()); + gfx::Range range(cursor, cursor + composition.text.length()); render_text_->SetCompositionRange(range); - ui::Range emphasized_range = GetFirstEmphasizedRange(composition); + gfx::Range emphasized_range = GetFirstEmphasizedRange(composition); if (emphasized_range.IsValid()) { // This is a workaround due to the lack of support in RenderText to draw // a thick underline. In a composition returned from an IME, the segment @@ -603,11 +603,11 @@ void TextfieldViewsModel::SetCompositionText( // marker instead to show this range. // TODO(yukawa, msw): Support thick underline in RenderText and remove // this workaround. - render_text_->SelectRange(ui::Range( + render_text_->SelectRange(gfx::Range( cursor + emphasized_range.GetMin(), cursor + emphasized_range.GetMax())); } else if (!composition.selection.is_empty()) { - render_text_->SelectRange(ui::Range( + render_text_->SelectRange(gfx::Range( cursor + composition.selection.GetMin(), cursor + composition.selection.GetMax())); } else { @@ -617,7 +617,7 @@ void TextfieldViewsModel::SetCompositionText( void TextfieldViewsModel::ConfirmCompositionText() { DCHECK(HasCompositionText()); - ui::Range range = render_text_->GetCompositionRange(); + gfx::Range range = render_text_->GetCompositionRange(); string16 text = GetText().substr(range.start(), range.length()); // TODO(oshima): current behavior on ChromeOS is a bit weird and not // sure exactly how this should work. Find out and fix if necessary. @@ -630,7 +630,7 @@ void TextfieldViewsModel::ConfirmCompositionText() { void TextfieldViewsModel::CancelCompositionText() { DCHECK(HasCompositionText()); - ui::Range range = render_text_->GetCompositionRange(); + gfx::Range range = render_text_->GetCompositionRange(); ClearComposition(); string16 new_text = GetText(); render_text_->SetText(new_text.erase(range.start(), range.length())); @@ -640,11 +640,11 @@ void TextfieldViewsModel::CancelCompositionText() { } void TextfieldViewsModel::ClearComposition() { - render_text_->SetCompositionRange(ui::Range::InvalidRange()); + render_text_->SetCompositionRange(gfx::Range::InvalidRange()); } -void TextfieldViewsModel::GetCompositionTextRange(ui::Range* range) const { - *range = ui::Range(render_text_->GetCompositionRange()); +void TextfieldViewsModel::GetCompositionTextRange(gfx::Range* range) const { + *range = gfx::Range(render_text_->GetCompositionRange()); } bool TextfieldViewsModel::HasCompositionText() const { @@ -681,7 +681,7 @@ void TextfieldViewsModel::ReplaceTextInternal(const string16& text, if (next == model.caret_pos()) render_text_->MoveCursorTo(model); else - render_text_->SelectRange(ui::Range(next, model.caret_pos())); + render_text_->SelectRange(gfx::Range(next, model.caret_pos())); } // Edit history is recorded in InsertText. InsertTextInternal(text, mergeable); @@ -705,7 +705,7 @@ void TextfieldViewsModel::ClearRedoHistory() { edit_history_.erase(delete_start, edit_history_.end()); } -void TextfieldViewsModel::ExecuteAndRecordDelete(ui::Range range, +void TextfieldViewsModel::ExecuteAndRecordDelete(gfx::Range range, bool mergeable) { size_t old_text_start = range.GetMin(); const string16 text = GetText().substr(old_text_start, range.length()); diff --git a/chromium/ui/views/controls/textfield/textfield_views_model.h b/chromium/ui/views/controls/textfield/textfield_views_model.h index ddbdd72e7dc..1af734054a9 100644 --- a/chromium/ui/views/controls/textfield/textfield_views_model.h +++ b/chromium/ui/views/controls/textfield/textfield_views_model.h @@ -19,13 +19,10 @@ #include "ui/views/views_export.h" namespace gfx { +class Range; class RenderText; } // namespace gfx -namespace ui { -class Range; -} // namespace ui - namespace views { namespace internal { @@ -144,7 +141,7 @@ class VIEWS_EXPORT TextfieldViewsModel { // The current composition text will be confirmed. The selection starts with // the range's start position, and ends with the range's end position, // therefore the cursor position becomes the end position. - void SelectRange(const ui::Range& range); + void SelectRange(const gfx::Range& range); // The current composition text will be confirmed. // render_text_'s selection model is set to |sel|. @@ -204,10 +201,10 @@ class VIEWS_EXPORT TextfieldViewsModel { const string16& text, size_t position); // Retrieves the text content in a given range. - string16 GetTextFromRange(const ui::Range& range) const; + string16 GetTextFromRange(const gfx::Range& range) const; // Retrieves the range containing all text in the model. - void GetTextRange(ui::Range* range) const; + void GetTextRange(gfx::Range* range) const; // Sets composition text and attributes. If there is composition text already, // it'll be replaced by the new one. Otherwise, current selection will be @@ -224,7 +221,7 @@ class VIEWS_EXPORT TextfieldViewsModel { void CancelCompositionText(); // Retrieves the range of current composition text. - void GetCompositionTextRange(ui::Range* range) const; + void GetCompositionTextRange(gfx::Range* range) const; // Returns true if there is composition text. bool HasCompositionText() const; @@ -258,7 +255,7 @@ class VIEWS_EXPORT TextfieldViewsModel { void ClearRedoHistory(); // Executes and records edit operations. - void ExecuteAndRecordDelete(ui::Range range, bool mergeable); + void ExecuteAndRecordDelete(gfx::Range range, bool mergeable); void ExecuteAndRecordReplaceSelection(internal::MergeType merge_type, const string16& text); void ExecuteAndRecordReplace(internal::MergeType merge_type, diff --git a/chromium/ui/views/controls/textfield/textfield_views_model_unittest.cc b/chromium/ui/views/controls/textfield/textfield_views_model_unittest.cc index 2b2d546a89a..f78ffba1ac1 100644 --- a/chromium/ui/views/controls/textfield/textfield_views_model_unittest.cc +++ b/chromium/ui/views/controls/textfield/textfield_views_model_unittest.cc @@ -12,7 +12,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/clipboard/clipboard.h" #include "ui/base/clipboard/scoped_clipboard_writer.h" -#include "ui/base/range/range.h" +#include "ui/gfx/range/range.h" #include "ui/gfx/render_text.h" #include "ui/views/controls/textfield/textfield.h" #include "ui/views/controls/textfield/textfield_views_model.h" @@ -276,19 +276,19 @@ TEST_F(TextfieldViewsModelTest, Selection) { // SelectAll(false) selects towards the end. model.SelectAll(false); EXPECT_STR_EQ("HELLO", model.GetSelectedText()); - EXPECT_EQ(ui::Range(0, 5), model.render_text()->selection()); + EXPECT_EQ(gfx::Range(0, 5), model.render_text()->selection()); // SelectAll(true) selects towards the beginning. model.SelectAll(true); EXPECT_STR_EQ("HELLO", model.GetSelectedText()); - EXPECT_EQ(ui::Range(5, 0), model.render_text()->selection()); + EXPECT_EQ(gfx::Range(5, 0), model.render_text()->selection()); // Select and move cursor. - model.SelectRange(ui::Range(1U, 3U)); + model.SelectRange(gfx::Range(1U, 3U)); EXPECT_STR_EQ("EL", model.GetSelectedText()); model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false); EXPECT_EQ(1U, model.GetCursorPosition()); - model.SelectRange(ui::Range(1U, 3U)); + model.SelectRange(gfx::Range(1U, 3U)); model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false); EXPECT_EQ(3U, model.GetCursorPosition()); @@ -318,20 +318,20 @@ TEST_F(TextfieldViewsModelTest, Selection_BidiWithNonSpacingMarks) { model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false); model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); - EXPECT_EQ(ui::Range(2, 3), model.render_text()->selection()); + EXPECT_EQ(gfx::Range(2, 3), model.render_text()->selection()); EXPECT_EQ(WideToUTF16(L"c"), model.GetSelectedText()); model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); - EXPECT_EQ(ui::Range(2, 7), model.render_text()->selection()); + EXPECT_EQ(gfx::Range(2, 7), model.render_text()->selection()); EXPECT_EQ(WideToUTF16(L"c\x05E9\x05BC\x05C1\x05B8"), model.GetSelectedText()); model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); - EXPECT_EQ(ui::Range(2, 3), model.render_text()->selection()); + EXPECT_EQ(gfx::Range(2, 3), model.render_text()->selection()); EXPECT_EQ(WideToUTF16(L"c"), model.GetSelectedText()); model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); - EXPECT_EQ(ui::Range(2, 10), model.render_text()->selection()); + EXPECT_EQ(gfx::Range(2, 10), model.render_text()->selection()); EXPECT_EQ(WideToUTF16(L"c\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8" L"d"), model.GetSelectedText()); @@ -634,7 +634,7 @@ TEST_F(TextfieldViewsModelTest, RangeTest) { TextfieldViewsModel model(NULL); model.Append(ASCIIToUTF16("HELLO WORLD")); model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false); - ui::Range range = model.render_text()->selection(); + gfx::Range range = model.render_text()->selection(); EXPECT_TRUE(range.is_empty()); EXPECT_EQ(0U, range.start()); EXPECT_EQ(0U, range.end()); @@ -697,42 +697,42 @@ TEST_F(TextfieldViewsModelTest, RangeTest) { TEST_F(TextfieldViewsModelTest, SelectRangeTest) { TextfieldViewsModel model(NULL); model.Append(ASCIIToUTF16("HELLO WORLD")); - ui::Range range(0, 6); + gfx::Range range(0, 6); EXPECT_FALSE(range.is_reversed()); model.SelectRange(range); EXPECT_STR_EQ("HELLO ", model.GetSelectedText()); - range = ui::Range(6, 1); + range = gfx::Range(6, 1); EXPECT_TRUE(range.is_reversed()); model.SelectRange(range); EXPECT_STR_EQ("ELLO ", model.GetSelectedText()); - range = ui::Range(2, 1000); + range = gfx::Range(2, 1000); EXPECT_FALSE(range.is_reversed()); model.SelectRange(range); EXPECT_STR_EQ("LLO WORLD", model.GetSelectedText()); - range = ui::Range(1000, 3); + range = gfx::Range(1000, 3); EXPECT_TRUE(range.is_reversed()); model.SelectRange(range); EXPECT_STR_EQ("LO WORLD", model.GetSelectedText()); - range = ui::Range(0, 0); + range = gfx::Range(0, 0); EXPECT_TRUE(range.is_empty()); model.SelectRange(range); EXPECT_TRUE(model.GetSelectedText().empty()); - range = ui::Range(3, 3); + range = gfx::Range(3, 3); EXPECT_TRUE(range.is_empty()); model.SelectRange(range); EXPECT_TRUE(model.GetSelectedText().empty()); - range = ui::Range(1000, 100); + range = gfx::Range(1000, 100); EXPECT_FALSE(range.is_empty()); model.SelectRange(range); EXPECT_TRUE(model.GetSelectedText().empty()); - range = ui::Range(1000, 1000); + range = gfx::Range(1000, 1000); EXPECT_TRUE(range.is_empty()); model.SelectRange(range); EXPECT_TRUE(model.GetSelectedText().empty()); @@ -742,60 +742,60 @@ TEST_F(TextfieldViewsModelTest, SelectionTest) { TextfieldViewsModel model(NULL); model.Append(ASCIIToUTF16("HELLO WORLD")); model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false); - ui::Range selection = model.render_text()->selection(); - EXPECT_EQ(ui::Range(0), selection); + gfx::Range selection = model.render_text()->selection(); + EXPECT_EQ(gfx::Range(0), selection); model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true); selection = model.render_text()->selection(); - EXPECT_EQ(ui::Range(0, 5), selection); + EXPECT_EQ(gfx::Range(0, 5), selection); model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true); selection = model.render_text()->selection(); - EXPECT_EQ(ui::Range(0, 4), selection); + EXPECT_EQ(gfx::Range(0, 4), selection); model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true); selection = model.render_text()->selection(); - EXPECT_EQ(ui::Range(0), selection); + EXPECT_EQ(gfx::Range(0), selection); // now from the end. model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false); selection = model.render_text()->selection(); - EXPECT_EQ(ui::Range(11), selection); + EXPECT_EQ(gfx::Range(11), selection); model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true); selection = model.render_text()->selection(); - EXPECT_EQ(ui::Range(11, 6), selection); + EXPECT_EQ(gfx::Range(11, 6), selection); model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); selection = model.render_text()->selection(); - EXPECT_EQ(ui::Range(11, 7), selection); + EXPECT_EQ(gfx::Range(11, 7), selection); model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true); selection = model.render_text()->selection(); - EXPECT_EQ(ui::Range(11), selection); + EXPECT_EQ(gfx::Range(11), selection); // Select All model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, true); selection = model.render_text()->selection(); - EXPECT_EQ(ui::Range(11, 0), selection); + EXPECT_EQ(gfx::Range(11, 0), selection); } TEST_F(TextfieldViewsModelTest, SelectSelectionModelTest) { TextfieldViewsModel model(NULL); model.Append(ASCIIToUTF16("HELLO WORLD")); - model.SelectSelectionModel(gfx::SelectionModel(ui::Range(0, 6), + model.SelectSelectionModel(gfx::SelectionModel(gfx::Range(0, 6), gfx::CURSOR_BACKWARD)); EXPECT_STR_EQ("HELLO ", model.GetSelectedText()); - model.SelectSelectionModel(gfx::SelectionModel(ui::Range(6, 1), + model.SelectSelectionModel(gfx::SelectionModel(gfx::Range(6, 1), gfx::CURSOR_FORWARD)); EXPECT_STR_EQ("ELLO ", model.GetSelectedText()); - model.SelectSelectionModel(gfx::SelectionModel(ui::Range(2, 1000), + model.SelectSelectionModel(gfx::SelectionModel(gfx::Range(2, 1000), gfx::CURSOR_BACKWARD)); EXPECT_STR_EQ("LLO WORLD", model.GetSelectedText()); - model.SelectSelectionModel(gfx::SelectionModel(ui::Range(1000, 3), + model.SelectSelectionModel(gfx::SelectionModel(gfx::Range(1000, 3), gfx::CURSOR_FORWARD)); EXPECT_STR_EQ("LO WORLD", model.GetSelectedText()); @@ -805,7 +805,7 @@ TEST_F(TextfieldViewsModelTest, SelectSelectionModelTest) { model.SelectSelectionModel(gfx::SelectionModel(3, gfx::CURSOR_FORWARD)); EXPECT_TRUE(model.GetSelectedText().empty()); - model.SelectSelectionModel(gfx::SelectionModel(ui::Range(1000, 100), + model.SelectSelectionModel(gfx::SelectionModel(gfx::Range(1000, 100), gfx::CURSOR_FORWARD)); EXPECT_TRUE(model.GetSelectedText().empty()); @@ -816,20 +816,20 @@ TEST_F(TextfieldViewsModelTest, SelectSelectionModelTest) { TEST_F(TextfieldViewsModelTest, CompositionTextTest) { TextfieldViewsModel model(this); model.Append(ASCIIToUTF16("1234590")); - model.SelectRange(ui::Range(5, 5)); + model.SelectRange(gfx::Range(5, 5)); EXPECT_FALSE(model.HasSelection()); EXPECT_EQ(5U, model.GetCursorPosition()); - ui::Range range; + gfx::Range range; model.GetTextRange(&range); - EXPECT_EQ(ui::Range(0, 7), range); + EXPECT_EQ(gfx::Range(0, 7), range); ui::CompositionText composition; composition.text = ASCIIToUTF16("678"); composition.underlines.push_back(ui::CompositionUnderline(0, 3, 0, false)); // Cursor should be at the end of composition when characters are just typed. - composition.selection = ui::Range(3, 3); + composition.selection = gfx::Range(3, 3); model.SetCompositionText(composition); EXPECT_TRUE(model.HasCompositionText()); EXPECT_FALSE(model.HasSelection()); @@ -839,24 +839,24 @@ TEST_F(TextfieldViewsModelTest, CompositionTextTest) { composition_text_confirmed_or_cleared_ = false; // Restart composition with targeting "67" in "678". - composition.selection = ui::Range(0, 2); + composition.selection = gfx::Range(0, 2); composition.underlines.clear(); composition.underlines.push_back(ui::CompositionUnderline(0, 2, 0, true)); composition.underlines.push_back(ui::CompositionUnderline(2, 3, 0, false)); model.SetCompositionText(composition); EXPECT_TRUE(model.HasCompositionText()); EXPECT_TRUE(model.HasSelection()); - EXPECT_EQ(ui::Range(5, 7), model.render_text()->selection()); + EXPECT_EQ(gfx::Range(5, 7), model.render_text()->selection()); model.GetTextRange(&range); EXPECT_EQ(10U, range.end()); EXPECT_STR_EQ("1234567890", model.GetText()); model.GetCompositionTextRange(&range); - EXPECT_EQ(ui::Range(5, 8), range); + EXPECT_EQ(gfx::Range(5, 8), range); // composition text - EXPECT_STR_EQ("456", model.GetTextFromRange(ui::Range(3, 6))); - EXPECT_EQ(ui::Range(5, 7), model.render_text()->selection()); + EXPECT_STR_EQ("456", model.GetTextFromRange(gfx::Range(3, 6))); + EXPECT_EQ(gfx::Range(5, 7), model.render_text()->selection()); EXPECT_FALSE(composition_text_confirmed_or_cleared_); model.CancelCompositionText(); @@ -954,7 +954,7 @@ TEST_F(TextfieldViewsModelTest, CompositionTextTest) { model.SetCompositionText(composition); gfx::SelectionModel sel( - ui::Range(model.render_text()->selection().start(), 0), + gfx::Range(model.render_text()->selection().start(), 0), gfx::CURSOR_FORWARD); model.MoveCursorTo(sel); EXPECT_TRUE(composition_text_confirmed_or_cleared_); @@ -962,7 +962,7 @@ TEST_F(TextfieldViewsModelTest, CompositionTextTest) { EXPECT_STR_EQ("678678", model.GetText()); model.SetCompositionText(composition); - model.SelectRange(ui::Range(0, 3)); + model.SelectRange(gfx::Range(0, 3)); EXPECT_TRUE(composition_text_confirmed_or_cleared_); composition_text_confirmed_or_cleared_ = false; EXPECT_STR_EQ("678", model.GetText()); @@ -1095,19 +1095,19 @@ TEST_F(TextfieldViewsModelTest, UndoRedo_SetText) { model.SetText(ASCIIToUTF16("www.google.com")); EXPECT_EQ(14U, model.GetCursorPosition()); EXPECT_STR_EQ("www.google.com", model.GetText()); - model.SelectRange(ui::Range(14, 1)); + model.SelectRange(gfx::Range(14, 1)); model.InsertChar('w'); EXPECT_STR_EQ("ww", model.GetText()); model.SetText(ASCIIToUTF16("www.google.com")); - model.SelectRange(ui::Range(14, 2)); + model.SelectRange(gfx::Range(14, 2)); model.InsertChar('w'); EXPECT_STR_EQ("www", model.GetText()); model.SetText(ASCIIToUTF16("www.google.com")); - model.SelectRange(ui::Range(14, 3)); + model.SelectRange(gfx::Range(14, 3)); model.InsertChar('.'); EXPECT_STR_EQ("www.", model.GetText()); model.SetText(ASCIIToUTF16("www.google.com")); - model.SelectRange(ui::Range(14, 4)); + model.SelectRange(gfx::Range(14, 4)); model.InsertChar('y'); EXPECT_STR_EQ("www.y", model.GetText()); model.SetText(ASCIIToUTF16("www.youtube.com")); @@ -1177,7 +1177,7 @@ TEST_F(TextfieldViewsModelTest, UndoRedo_CutCopyPasteTest) { model.SetText(ASCIIToUTF16("ABCDE")); EXPECT_FALSE(model.Redo()); // nothing to redo // Cut - model.SelectRange(ui::Range(1, 3)); + model.SelectRange(gfx::Range(1, 3)); model.Cut(); EXPECT_STR_EQ("ADE", model.GetText()); EXPECT_EQ(1U, model.GetCursorPosition()); @@ -1240,11 +1240,11 @@ TEST_F(TextfieldViewsModelTest, UndoRedo_CutCopyPasteTest) { EXPECT_FALSE(model.Redo()); // with SelectRange - model.SelectRange(ui::Range(1, 3)); + model.SelectRange(gfx::Range(1, 3)); EXPECT_TRUE(model.Cut()); EXPECT_STR_EQ("ABCBCDE", model.GetText()); EXPECT_EQ(1U, model.GetCursorPosition()); - model.SelectRange(ui::Range(1, 1)); + model.SelectRange(gfx::Range(1, 1)); EXPECT_FALSE(model.Cut()); model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false); EXPECT_TRUE(model.Paste()); @@ -1263,7 +1263,7 @@ TEST_F(TextfieldViewsModelTest, UndoRedo_CutCopyPasteTest) { model.SetText(ASCIIToUTF16("12345")); EXPECT_STR_EQ("12345", model.GetText()); EXPECT_EQ(5U, model.GetCursorPosition()); - model.SelectRange(ui::Range(1, 3)); + model.SelectRange(gfx::Range(1, 3)); model.Copy(); // Copy "23" EXPECT_STR_EQ("12345", model.GetText()); EXPECT_EQ(3U, model.GetCursorPosition()); @@ -1297,7 +1297,7 @@ TEST_F(TextfieldViewsModelTest, UndoRedo_CutCopyPasteTest) { EXPECT_STR_EQ("1232345", model.GetText()); // Test using SelectRange - model.SelectRange(ui::Range(1, 3)); + model.SelectRange(gfx::Range(1, 3)); model.Copy(); EXPECT_STR_EQ("1232345", model.GetText()); model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false); @@ -1381,28 +1381,28 @@ TEST_F(TextfieldViewsModelTest, UndoRedo_ReplaceTest) { SCOPED_TRACE("forward & insert by cursor"); TextfieldViewsModel model(NULL); model.SetText(ASCIIToUTF16("abcd")); - model.SelectRange(ui::Range(1, 3)); + model.SelectRange(gfx::Range(1, 3)); RunInsertReplaceTest(model); } { SCOPED_TRACE("backward & insert by cursor"); TextfieldViewsModel model(NULL); model.SetText(ASCIIToUTF16("abcd")); - model.SelectRange(ui::Range(3, 1)); + model.SelectRange(gfx::Range(3, 1)); RunInsertReplaceTest(model); } { SCOPED_TRACE("forward & overwrite by cursor"); TextfieldViewsModel model(NULL); model.SetText(ASCIIToUTF16("abcd")); - model.SelectRange(ui::Range(1, 3)); + model.SelectRange(gfx::Range(1, 3)); RunOverwriteReplaceTest(model); } { SCOPED_TRACE("backward & overwrite by cursor"); TextfieldViewsModel model(NULL); model.SetText(ASCIIToUTF16("abcd")); - model.SelectRange(ui::Range(3, 1)); + model.SelectRange(gfx::Range(3, 1)); RunOverwriteReplaceTest(model); } // By SelectRange API @@ -1410,28 +1410,28 @@ TEST_F(TextfieldViewsModelTest, UndoRedo_ReplaceTest) { SCOPED_TRACE("forward & insert by SelectRange"); TextfieldViewsModel model(NULL); model.SetText(ASCIIToUTF16("abcd")); - model.SelectRange(ui::Range(1, 3)); + model.SelectRange(gfx::Range(1, 3)); RunInsertReplaceTest(model); } { SCOPED_TRACE("backward & insert by SelectRange"); TextfieldViewsModel model(NULL); model.SetText(ASCIIToUTF16("abcd")); - model.SelectRange(ui::Range(3, 1)); + model.SelectRange(gfx::Range(3, 1)); RunInsertReplaceTest(model); } { SCOPED_TRACE("forward & overwrite by SelectRange"); TextfieldViewsModel model(NULL); model.SetText(ASCIIToUTF16("abcd")); - model.SelectRange(ui::Range(1, 3)); + model.SelectRange(gfx::Range(1, 3)); RunOverwriteReplaceTest(model); } { SCOPED_TRACE("backward & overwrite by SelectRange"); TextfieldViewsModel model(NULL); model.SetText(ASCIIToUTF16("abcd")); - model.SelectRange(ui::Range(3, 1)); + model.SelectRange(gfx::Range(3, 1)); RunOverwriteReplaceTest(model); } } @@ -1442,7 +1442,7 @@ TEST_F(TextfieldViewsModelTest, UndoRedo_CompositionText) { ui::CompositionText composition; composition.text = ASCIIToUTF16("abc"); composition.underlines.push_back(ui::CompositionUnderline(0, 3, 0, false)); - composition.selection = ui::Range(2, 3); + composition.selection = gfx::Range(2, 3); model.SetText(ASCIIToUTF16("ABCDE")); model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false); diff --git a/chromium/ui/views/controls/tree/tree_view.cc b/chromium/ui/views/controls/tree/tree_view.cc index 0157902fad4..78d4693e4a7 100644 --- a/chromium/ui/views/controls/tree/tree_view.cc +++ b/chromium/ui/views/controls/tree/tree_view.cc @@ -10,9 +10,9 @@ #include "base/message_loop/message_loop.h" #include "grit/ui_resources.h" #include "ui/base/accessibility/accessible_view_state.h" -#include "ui/base/events/event.h" -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/canvas.h" #include "ui/gfx/image/image.h" #include "ui/gfx/rect_conversions.h" diff --git a/chromium/ui/views/controls/tree/tree_view_controller.h b/chromium/ui/views/controls/tree/tree_view_controller.h index 38e7fcc85e4..b1ebf2b0b0c 100644 --- a/chromium/ui/views/controls/tree/tree_view_controller.h +++ b/chromium/ui/views/controls/tree/tree_view_controller.h @@ -5,7 +5,7 @@ #ifndef UI_VIEWS_CONTROLS_TREE_TREE_VIEW_CONTROLLER_H_ #define UI_VIEWS_CONTROLS_TREE_TREE_VIEW_CONTROLLER_H_ -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/views/views_export.h" namespace ui { diff --git a/chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_aurax11.cc b/chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_aurax11.cc index 41c90ff7f2f..7e09af947b5 100644 --- a/chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_aurax11.cc +++ b/chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_aurax11.cc @@ -6,7 +6,7 @@ #include "base/logging.h" #include "content/public/browser/native_web_keyboard_event.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" #include "ui/views/focus/focus_manager.h" using content::NativeWebKeyboardEvent; diff --git a/chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_win.cc b/chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_win.cc index fd82608bd18..b30b5576c3e 100644 --- a/chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_win.cc +++ b/chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_win.cc @@ -6,7 +6,7 @@ #include "base/logging.h" #include "content/public/browser/native_web_keyboard_event.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" #include "ui/views/focus/focus_manager.h" using content::NativeWebKeyboardEvent; diff --git a/chromium/ui/views/controls/webview/web_dialog_view.cc b/chromium/ui/views/controls/webview/web_dialog_view.cc index 15173791d03..ff9d63bb45b 100644 --- a/chromium/ui/views/controls/webview/web_dialog_view.cc +++ b/chromium/ui/views/controls/webview/web_dialog_view.cc @@ -14,7 +14,7 @@ #include "content/public/browser/notification_types.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/views/controls/webview/webview.h" #include "ui/views/layout/fill_layout.h" #include "ui/views/widget/root_view.h" @@ -23,7 +23,7 @@ #include "ui/web_dialogs/web_dialog_ui.h" #if defined(USE_AURA) -#include "ui/base/events/event.h" +#include "ui/events/event.h" #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" #include "ui/views/widget/native_widget_aura.h" #endif diff --git a/chromium/ui/views/controls/webview/webview.cc b/chromium/ui/views/controls/webview/webview.cc index 89ac03758e5..9169ac0ecbf 100644 --- a/chromium/ui/views/controls/webview/webview.cc +++ b/chromium/ui/views/controls/webview/webview.cc @@ -4,6 +4,7 @@ #include "ui/views/controls/webview/webview.h" +#include "content/public/browser/browser_accessibility_state.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/notification_details.h" @@ -17,7 +18,7 @@ #include "ipc/ipc_message.h" #include "ui/base/accessibility/accessibility_types.h" #include "ui/base/accessibility/accessible_view_state.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" #include "ui/views/accessibility/native_view_accessibility.h" #include "ui/views/controls/native/native_view_host.h" #include "ui/views/focus/focus_manager.h" @@ -34,6 +35,8 @@ const char WebView::kViewClassName[] = "WebView"; WebView::WebView(content::BrowserContext* browser_context) : wcv_holder_(new NativeViewHost), web_contents_(NULL), + embed_fullscreen_widget_mode_enabled_(false), + is_embedding_fullscreen_widget_(false), browser_context_(browser_context), allow_accelerators_(false) { AddChildView(wcv_holder_); @@ -63,11 +66,35 @@ void WebView::SetWebContents(content::WebContents* web_contents) { if (web_contents == web_contents_) return; DetachWebContents(); - wc_owner_.reset(); + if (wc_owner_ != web_contents) + wc_owner_.reset(); web_contents_ = web_contents; + if (embed_fullscreen_widget_mode_enabled_) { + WebContentsObserver::Observe(web_contents_); + is_embedding_fullscreen_widget_ = + web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView(); + } else { + is_embedding_fullscreen_widget_ = false; + } AttachWebContents(); } +void WebView::SetEmbedFullscreenWidgetMode(bool enable) { + bool should_be_embedded = enable; + if (!embed_fullscreen_widget_mode_enabled_ && enable) { + DCHECK(!is_embedding_fullscreen_widget_); + embed_fullscreen_widget_mode_enabled_ = true; + WebContentsObserver::Observe(web_contents_); + should_be_embedded = + web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView(); + } else if (embed_fullscreen_widget_mode_enabled_ && !enable) { + embed_fullscreen_widget_mode_enabled_ = false; + WebContentsObserver::Observe(NULL); + } + if (should_be_embedded != is_embedding_fullscreen_widget_) + ReattachForFullscreenChange(should_be_embedded); +} + void WebView::LoadInitialURL(const GURL& url) { GetWebContents()->GetController().LoadURL( url, content::Referrer(), content::PAGE_TRANSITION_AUTO_TOPLEVEL, @@ -125,8 +152,16 @@ bool WebView::IsFocusable() const { } void WebView::OnFocus() { - if (web_contents_) + if (!web_contents_) + return; + if (is_embedding_fullscreen_widget_) { + content::RenderWidgetHostView* const current_fs_view = + web_contents_->GetFullscreenRenderWidgetHostView(); + if (current_fs_view) + current_fs_view->Focus(); + } else { web_contents_->GetView()->Focus(); + } } void WebView::AboutToRequestFocusFromTabTraversal(bool reverse) { @@ -162,15 +197,13 @@ void WebView::Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) { if (type == content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED) { - std::pair<content::RenderViewHost*, content::RenderViewHost*>* - switched_details = - content::Details<std::pair<content::RenderViewHost*, - content::RenderViewHost*> >( - details).ptr(); - RenderViewHostChanged(switched_details->first, - switched_details->second); + FocusManager* const focus_manager = GetFocusManager(); + if (focus_manager && focus_manager->GetFocusedView() == this) + OnFocus(); } else if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { - WebContentsDestroyed(content::Source<content::WebContents>(source).ptr()); + DCHECK(content::Source<content::WebContents>(source).ptr() == + web_contents_); + SetWebContents(NULL); } else { NOTREACHED(); } @@ -185,26 +218,22 @@ void WebView::WebContentsFocused(content::WebContents* web_contents) { OnWebContentsFocused(web_contents_); } +bool WebView::EmbedsFullscreenWidget() const { + DCHECK(wc_owner_.get()); + return embed_fullscreen_widget_mode_enabled_; +} + //////////////////////////////////////////////////////////////////////////////// -// WebView, AccessibleWebView implementation: +// WebView, content::WebContentsObserver implementation: -gfx::NativeViewAccessible WebView::AccessibleObjectFromChildId(long child_id) { -#if defined(OS_WIN) && defined(USE_AURA) - if (!web_contents_) - return NULL; - content::RenderWidgetHostView* host_view = - web_contents_->GetRenderWidgetHostView(); - if (host_view) - return host_view->AccessibleObjectFromChildId(child_id); - return NULL; -#else - NOTIMPLEMENTED(); - return NULL; -#endif +void WebView::DidShowFullscreenWidget(int routing_id) { + DCHECK(embed_fullscreen_widget_mode_enabled_); + ReattachForFullscreenChange(true); } -View* WebView::AsView() { - return this; +void WebView::DidDestroyFullscreenWidget(int routing_id) { + DCHECK(embed_fullscreen_widget_mode_enabled_); + ReattachForFullscreenChange(false); } //////////////////////////////////////////////////////////////////////////////// @@ -213,66 +242,69 @@ View* WebView::AsView() { void WebView::AttachWebContents() { // Prevents attachment if the WebView isn't already in a Widget, or it's // already attached. - if (!GetWidget() || !web_contents_ || - wcv_holder_->native_view() == web_contents_->GetView()->GetNativeView()) { + if (!GetWidget() || !web_contents_) return; - } - - if (web_contents_) { - wcv_holder_->Attach(web_contents_->GetView()->GetNativeView()); - // The WebContentsView will not be focused automatically when it is - // attached, so we need to pass on focus to it if the FocusManager thinks - // the WebView is focused. Note that not every Widget has a focus manager. - FocusManager* focus_manager = GetFocusManager(); - if (focus_manager && focus_manager->GetFocusedView() == this) - web_contents_->GetView()->Focus(); - - registrar_.Add( - this, - content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, - content::Source<content::NavigationController>( - &web_contents_->GetController())); - registrar_.Add( - this, - content::NOTIFICATION_WEB_CONTENTS_DESTROYED, - content::Source<content::WebContents>(web_contents_)); - } + const gfx::NativeView view_to_attach = is_embedding_fullscreen_widget_ ? + web_contents_->GetFullscreenRenderWidgetHostView()->GetNativeView() : + web_contents_->GetView()->GetNativeView(); + if (wcv_holder_->native_view() == view_to_attach) + return; + wcv_holder_->Attach(view_to_attach); + + // The view will not be focused automatically when it is attached, so we need + // to pass on focus to it if the FocusManager thinks the view is focused. Note + // that not every Widget has a focus manager. + FocusManager* const focus_manager = GetFocusManager(); + if (focus_manager && focus_manager->GetFocusedView() == this) + OnFocus(); + + registrar_.Add( + this, + content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, + content::Source<content::NavigationController>( + &web_contents_->GetController())); + registrar_.Add( + this, + content::NOTIFICATION_WEB_CONTENTS_DESTROYED, + content::Source<content::WebContents>(web_contents_)); #if defined(OS_WIN) && defined(USE_AURA) - web_contents_->SetParentNativeViewAccessible( - parent()->GetNativeViewAccessible()); + if (!is_embedding_fullscreen_widget_) { + web_contents_->SetParentNativeViewAccessible( + parent()->GetNativeViewAccessible()); + } #endif } void WebView::DetachWebContents() { if (web_contents_) { wcv_holder_->Detach(); -#if defined(OS_WIN) && !defined(USE_AURA) - // TODO(beng): This should either not be necessary, or be done implicitly by - // NativeViewHostWin on Detach(). As it stands, this is needed so that the - // view of the detached contents knows to tell the renderer it's been - // hidden. - // - // Moving this out of here would also mean we wouldn't be potentially - // calling member functions on a half-destroyed WebContents. - ShowWindow(web_contents_->GetView()->GetNativeView(), SW_HIDE); -#elif defined(OS_WIN) && defined(USE_AURA) - web_contents_->SetParentNativeViewAccessible(NULL); +#if defined(OS_WIN) + if (!is_embedding_fullscreen_widget_) { +#if !defined(USE_AURA) + // TODO(beng): This should either not be necessary, or be done implicitly + // by NativeViewHostWin on Detach(). As it stands, this is needed so that + // the of the detached contents knows to tell the renderer it's been + // hidden. + // + // Moving this out of here would also mean we wouldn't be potentially + // calling member functions on a half-destroyed WebContents. + ShowWindow(web_contents_->GetView()->GetNativeView(), SW_HIDE); +#else + web_contents_->SetParentNativeViewAccessible(NULL); +#endif + } #endif } registrar_.RemoveAll(); } -void WebView::RenderViewHostChanged(content::RenderViewHost* old_host, - content::RenderViewHost* new_host) { - if (GetFocusManager()->GetFocusedView() == this) - web_contents_->GetView()->Focus(); -} - -void WebView::WebContentsDestroyed(content::WebContents* web_contents) { - DCHECK(web_contents == web_contents_); - SetWebContents(NULL); +void WebView::ReattachForFullscreenChange(bool enter_fullscreen) { + DetachWebContents(); + is_embedding_fullscreen_widget_ = enter_fullscreen && + web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView(); + AttachWebContents(); } content::WebContents* WebView::CreateWebContents( diff --git a/chromium/ui/views/controls/webview/webview.h b/chromium/ui/views/controls/webview/webview.h index cec510259e1..7e50914131c 100644 --- a/chromium/ui/views/controls/webview/webview.h +++ b/chromium/ui/views/controls/webview/webview.h @@ -10,6 +10,7 @@ #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/web_contents_delegate.h" +#include "content/public/browser/web_contents_observer.h" #include "ui/views/accessibility/native_view_accessibility.h" #include "ui/views/controls/webview/webview_export.h" #include "ui/views/view.h" @@ -25,7 +26,7 @@ class NativeViewHost; class WEBVIEW_EXPORT WebView : public View, public content::NotificationObserver, public content::WebContentsDelegate, - public AccessibleWebView { + public content::WebContentsObserver { public: static const char kViewClassName[]; @@ -44,6 +45,12 @@ class WEBVIEW_EXPORT WebView : public View, // those it implicitly creates via GetWebContents() above. void SetWebContents(content::WebContents* web_contents); + // If |mode| is true, WebView will register itself with WebContents as a + // WebContentsObserver, monitor for the showing/destruction of fullscreen + // render widgets, and alter its child view hierarchy to embed the fullscreen + // widget or restore the normal WebContentsView. + void SetEmbedFullscreenWidgetMode(bool mode); + content::WebContents* web_contents() { return web_contents_; } content::BrowserContext* browser_context() { return browser_context_; } @@ -83,11 +90,6 @@ class WEBVIEW_EXPORT WebView : public View, // Overridden from View: virtual const char* GetClassName() const OVERRIDE; - // Overridden from AccessibleWebView: - virtual gfx::NativeViewAccessible AccessibleObjectFromChildId( - long child_id) OVERRIDE; - virtual View* AsView() OVERRIDE; - private: // Overridden from View: virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE; @@ -109,13 +111,19 @@ class WEBVIEW_EXPORT WebView : public View, // Overridden from content::WebContentsDelegate: virtual void WebContentsFocused(content::WebContents* web_contents) OVERRIDE; + virtual bool EmbedsFullscreenWidget() const OVERRIDE; + + // Overridden from content::WebContentsObserver: + virtual void DidShowFullscreenWidget(int routing_id) OVERRIDE; + virtual void DidDestroyFullscreenWidget(int routing_id) OVERRIDE; + // Workaround for MSVC++ linker bug/feature that requires + // instantiation of the inline IPC::Listener methods in all translation units. + virtual void OnChannelConnected(int32 peer_id) OVERRIDE {} + virtual void OnChannelError() OVERRIDE {} void AttachWebContents(); void DetachWebContents(); - - void RenderViewHostChanged(content::RenderViewHost* old_host, - content::RenderViewHost* new_host); - void WebContentsDestroyed(content::WebContents* web_contents); + void ReattachForFullscreenChange(bool enter_fullscreen); // Create a regular or test web contents (based on whether we're running // in a unit test or not). @@ -126,6 +134,12 @@ class WEBVIEW_EXPORT WebView : public View, NativeViewHost* wcv_holder_; scoped_ptr<content::WebContents> wc_owner_; content::WebContents* web_contents_; + // When true, WebView observes WebContents and auto-embeds fullscreen widgets + // as a child view. + bool embed_fullscreen_widget_mode_enabled_; + // Set to true while WebView is embedding a fullscreen widget view as a child + // view instead of the normal WebContentsView render view. + bool is_embedding_fullscreen_widget_; content::BrowserContext* browser_context_; content::NotificationRegistrar registrar_; bool allow_accelerators_; diff --git a/chromium/ui/views/corewm/capture_controller.cc b/chromium/ui/views/corewm/capture_controller.cc new file mode 100644 index 00000000000..9a46988e626 --- /dev/null +++ b/chromium/ui/views/corewm/capture_controller.cc @@ -0,0 +1,139 @@ +// Copyright (c) 2012 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 "ui/views/corewm/capture_controller.h" + +#include "ui/aura/root_window.h" +#include "ui/aura/window.h" + +namespace views { +namespace corewm { + +//////////////////////////////////////////////////////////////////////////////// +// CaptureController, public: + +void CaptureController::Attach(aura::RootWindow* root) { + DCHECK_EQ(0u, root_windows_.count(root)); + root_windows_.insert(root); + aura::client::SetCaptureClient(root, this); +} + +void CaptureController::Detach(aura::RootWindow* root) { + CHECK(!root->Contains(capture_window_)); + root_windows_.erase(root); + aura::client::SetCaptureClient(root, NULL); +} + +//////////////////////////////////////////////////////////////////////////////// +// CaptureController, client::CaptureClient implementation: + +void CaptureController::SetCapture(aura::Window* new_capture_window) { + if (capture_window_ == new_capture_window) + return; + + // Make sure window has a root window. + CHECK(!new_capture_window || new_capture_window->GetRootWindow()); + CHECK(!capture_window_ || capture_window_->GetRootWindow()); + + aura::Window* old_capture_window = capture_window_; + aura::RootWindow* old_capture_root = old_capture_window ? + old_capture_window->GetRootWindow() : NULL; + + // Copy the list in case it's modified out from under us. + RootWindows root_windows(root_windows_); + + // If we're actually starting capture, then cancel any touches/gestures + // that aren't already locked to the new window, and transfer any on the + // old capture window to the new one. When capture is released we have no + // distinction between the touches/gestures that were in the window all + // along (and so shouldn't be canceled) and those that got moved, so + // just leave them all where they are. + if (new_capture_window) { + for (RootWindows::const_iterator i = root_windows.begin(); + i != root_windows.end(); ++i) { + (*i)->gesture_recognizer()->TransferEventsTo( + old_capture_window, new_capture_window); + } + } + + capture_window_ = new_capture_window; + + for (RootWindows::const_iterator i = root_windows.begin(); + i != root_windows.end(); ++i) { + (*i)->UpdateCapture(old_capture_window, new_capture_window); + } + + aura::RootWindow* capture_root = + capture_window_ ? capture_window_->GetRootWindow() : NULL; + if (capture_root != old_capture_root) { + if (old_capture_root) + old_capture_root->ReleaseNativeCapture(); + if (capture_root) + capture_root->SetNativeCapture(); + } +} + +void CaptureController::ReleaseCapture(aura::Window* window) { + if (capture_window_ != window) + return; + SetCapture(NULL); +} + +aura::Window* CaptureController::GetCaptureWindow() { + return capture_window_; +} + +//////////////////////////////////////////////////////////////////////////////// +// CaptureController, private: + +CaptureController::CaptureController() + : capture_window_(NULL) { +} + +CaptureController::~CaptureController() { +} + +//////////////////////////////////////////////////////////////////////////////// +// ScopedCaptureClient: + +// static +CaptureController* ScopedCaptureClient::capture_controller_ = NULL; + +ScopedCaptureClient::ScopedCaptureClient(aura::RootWindow* root) + : root_window_(root) { + root->AddObserver(this); + if (!capture_controller_) + capture_controller_ = new CaptureController; + capture_controller_->Attach(root); +} + +ScopedCaptureClient::~ScopedCaptureClient() { + Shutdown(); +} + +// static +bool ScopedCaptureClient::IsActive() { + return capture_controller_ && capture_controller_->is_active(); +} + +void ScopedCaptureClient::OnWindowDestroyed(aura::Window* window) { + DCHECK_EQ(window, root_window_); + Shutdown(); +} + +void ScopedCaptureClient::Shutdown() { + if (!root_window_) + return; + + root_window_->RemoveObserver(this); + capture_controller_->Detach(root_window_); + if (!capture_controller_->is_active()) { + delete capture_controller_; + capture_controller_ = NULL; + } + root_window_ = NULL; +} + +} // namespace corewm +} // namespace views diff --git a/chromium/ui/views/corewm/capture_controller.h b/chromium/ui/views/corewm/capture_controller.h new file mode 100644 index 00000000000..343c3c0a87b --- /dev/null +++ b/chromium/ui/views/corewm/capture_controller.h @@ -0,0 +1,87 @@ +// Copyright (c) 2012 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. + +#ifndef UI_VIEWS_COREWM_CAPTURE_CONTROLLER_H_ +#define UI_VIEWS_COREWM_CAPTURE_CONTROLLER_H_ + +#include <set> + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "ui/aura/client/capture_client.h" +#include "ui/aura/window_observer.h" +#include "ui/views/views_export.h" + +namespace views { +namespace corewm { + +// Internal CaptureClient implementation. See ScopedCaptureClient for details. +class VIEWS_EXPORT CaptureController : public aura::client::CaptureClient { + public: + // Adds |root| to the list of RootWindows notified when capture changes. + void Attach(aura::RootWindow* root); + + // Removes |root| from the list of RootWindows notified when capture changes. + void Detach(aura::RootWindow* root); + + // Returns true if this CaptureController is installed on at least one + // RootWindow. + bool is_active() const { return !root_windows_.empty(); } + + // Overridden from aura::client::CaptureClient: + virtual void SetCapture(aura::Window* window) OVERRIDE; + virtual void ReleaseCapture(aura::Window* window) OVERRIDE; + virtual aura::Window* GetCaptureWindow() OVERRIDE; + + private: + friend class ScopedCaptureClient; + typedef std::set<aura::RootWindow*> RootWindows; + + CaptureController(); + virtual ~CaptureController(); + + // The current capture window. NULL if there is no capture window. + aura::Window* capture_window_; + + // Set of RootWindows notified when capture changes. + RootWindows root_windows_; + + DISALLOW_COPY_AND_ASSIGN(CaptureController); +}; + +// ScopedCaptureClient is responsible for creating a CaptureClient for a +// RootWindow. Specifically it creates a single CaptureController that is shared +// among all ScopedCaptureClients and adds the RootWindow to it. +class VIEWS_EXPORT ScopedCaptureClient : public aura::WindowObserver { + public: + explicit ScopedCaptureClient(aura::RootWindow* root); + virtual ~ScopedCaptureClient(); + + // Returns true if there is a CaptureController with at least one RootWindow. + static bool IsActive(); + + aura::client::CaptureClient* capture_client() { + return capture_controller_; + } + + // Overridden from aura::WindowObserver: + virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE; + + private: + // Invoked from destructor and OnWindowDestroyed() to cleanup. + void Shutdown(); + + // The single CaptureController instance. + static CaptureController* capture_controller_; + + // RootWindow this ScopedCaptureClient was create for. + aura::RootWindow* root_window_; + + DISALLOW_COPY_AND_ASSIGN(ScopedCaptureClient); +}; + +} // namespace corewm +} // namespace views + +#endif // UI_VIEWS_COREWM_CAPTURE_CONTROLLER_H_ diff --git a/chromium/ui/views/corewm/capture_controller_unittest.cc b/chromium/ui/views/corewm/capture_controller_unittest.cc new file mode 100644 index 00000000000..46a8a2e4327 --- /dev/null +++ b/chromium/ui/views/corewm/capture_controller_unittest.cc @@ -0,0 +1,169 @@ +// Copyright (c) 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 "ui/views/corewm/capture_controller.h" + +#include "base/logging.h" +#include "ui/aura/env.h" +#include "ui/aura/root_window.h" +#include "ui/aura/test/aura_test_base.h" +#include "ui/aura/test/event_generator.h" +#include "ui/aura/test/test_screen.h" +#include "ui/aura/test/test_window_delegate.h" +#include "ui/events/event.h" +#include "ui/events/event_utils.h" +#include "ui/views/test/views_test_base.h" +#include "ui/views/view.h" +#include "ui/views/widget/root_view.h" +#include "ui/views/widget/widget.h" + +#if !defined(OS_CHROMEOS) +#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" +#include "ui/views/widget/desktop_aura/desktop_screen_position_client.h" +#endif + +namespace views { + +class CaptureControllerTest : public aura::test::AuraTestBase { + public: + CaptureControllerTest() {} + + virtual void SetUp() OVERRIDE { + AuraTestBase::SetUp(); + capture_controller_.reset(new corewm::ScopedCaptureClient(root_window())); + + second_root_.reset(new aura::RootWindow( + aura::RootWindow::CreateParams(gfx::Rect(0, 0, 800, 600)))); + second_root_->Init(); + second_root_->Show(); + second_root_->SetHostSize(gfx::Size(800, 600)); + second_capture_controller_.reset( + new corewm::ScopedCaptureClient(second_root_.get())); + +#if !defined(OS_CHROMEOS) + desktop_position_client_.reset(new DesktopScreenPositionClient()); + aura::client::SetScreenPositionClient(root_window(), + desktop_position_client_.get()); + + second_desktop_position_client_.reset(new DesktopScreenPositionClient()); + aura::client::SetScreenPositionClient( + second_root_.get(), + second_desktop_position_client_.get()); +#endif + } + + virtual void TearDown() OVERRIDE { + RunAllPendingInMessageLoop(); + +#if !defined(OS_CHROMEOS) + second_desktop_position_client_.reset(); +#endif + second_capture_controller_.reset(); + + // Kill any active compositors before we hit the compositor shutdown paths. + second_root_.reset(); + +#if !defined(OS_CHROMEOS) + desktop_position_client_.reset(); +#endif + capture_controller_.reset(); + + AuraTestBase::TearDown(); + } + + aura::Window* GetCaptureWindow() { + return capture_controller_->capture_client()->GetCaptureWindow(); + } + + aura::Window* GetSecondCaptureWindow() { + return second_capture_controller_->capture_client()->GetCaptureWindow(); + } + + scoped_ptr<corewm::ScopedCaptureClient> capture_controller_; + scoped_ptr<aura::RootWindow> second_root_; + scoped_ptr<corewm::ScopedCaptureClient> second_capture_controller_; +#if !defined(OS_CHROMEOS) + scoped_ptr<aura::client::ScreenPositionClient> desktop_position_client_; + scoped_ptr<aura::client::ScreenPositionClient> + second_desktop_position_client_; +#endif + + DISALLOW_COPY_AND_ASSIGN(CaptureControllerTest); +}; + +// Makes sure that internal details that are set on mouse down (such as +// mouse_pressed_handler()) are cleared when another root window takes capture. +TEST_F(CaptureControllerTest, ResetMouseEventHandlerOnCapture) { + // Create a window inside the RootWindow. + scoped_ptr<aura::Window> w1(CreateNormalWindow(1, root_window(), NULL)); + + // Make a synthesized mouse down event. Ensure that the RootWindow will + // dispatch further mouse events to |w1|. + ui::MouseEvent mouse_pressed_event(ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), + gfx::Point(5, 5), 0); + root_window()->AsRootWindowHostDelegate()->OnHostMouseEvent( + &mouse_pressed_event); + EXPECT_EQ(w1.get(), root_window()->mouse_pressed_handler()); + + // Build a window in the second RootWindow. + scoped_ptr<aura::Window> w2(CreateNormalWindow(2, second_root_.get(), NULL)); + + // The act of having the second window take capture should clear out mouse + // pressed handler in the first RootWindow. + w2->SetCapture(); + EXPECT_EQ(NULL, root_window()->mouse_pressed_handler()); +} + +// Makes sure that when one window gets capture, it forces the release on the +// other. This is needed has to be handled explicitly on Linux, and is a sanity +// check on Windows. +TEST_F(CaptureControllerTest, ResetOtherWindowCaptureOnCapture) { + // Create a window inside the RootWindow. + scoped_ptr<aura::Window> w1(CreateNormalWindow(1, root_window(), NULL)); + w1->SetCapture(); + // Both capture clients should return the same capture window. + EXPECT_EQ(w1.get(), GetCaptureWindow()); + EXPECT_EQ(w1.get(), GetSecondCaptureWindow()); + + // Build a window in the second RootWindow and give it capture. Both capture + // clients should return the same capture window. + scoped_ptr<aura::Window> w2(CreateNormalWindow(2, second_root_.get(), NULL)); + w2->SetCapture(); + EXPECT_EQ(w2.get(), GetCaptureWindow()); + EXPECT_EQ(w2.get(), GetSecondCaptureWindow()); +} + +// Verifies the touch target for the RootWindow gets reset on releasing capture. +TEST_F(CaptureControllerTest, TouchTargetResetOnCaptureChange) { + // Create a window inside the RootWindow. + scoped_ptr<aura::Window> w1(CreateNormalWindow(1, root_window(), NULL)); + aura::test::EventGenerator event_generator1(root_window()); + event_generator1.PressTouch(); + w1->SetCapture(); + // Both capture clients should return the same capture window. + EXPECT_EQ(w1.get(), GetCaptureWindow()); + EXPECT_EQ(w1.get(), GetSecondCaptureWindow()); + + // Build a window in the second RootWindow and give it capture. Both capture + // clients should return the same capture window. + scoped_ptr<aura::Window> w2(CreateNormalWindow(2, second_root_.get(), NULL)); + w2->SetCapture(); + EXPECT_EQ(w2.get(), GetCaptureWindow()); + EXPECT_EQ(w2.get(), GetSecondCaptureWindow()); + + // Release capture on the window. Releasing capture should reset the touch + // target of the first RootWindow (as it no longer contains the capture + // target). + w2->ReleaseCapture(); + EXPECT_EQ(static_cast<aura::Window*>(NULL), GetCaptureWindow()); + EXPECT_EQ(static_cast<aura::Window*>(NULL), GetSecondCaptureWindow()); + ui::TouchEvent touch_event( + ui::ET_TOUCH_PRESSED, gfx::Point(), 0, 0, ui::EventTimeForNow(), 1.0f, + 1.0f, 1.0f, 1.0f); + EXPECT_EQ(static_cast<ui::GestureConsumer*>(NULL), + root_window()->gesture_recognizer()->GetTouchLockedTarget( + &touch_event)); +} + +} // namespace views diff --git a/chromium/ui/views/corewm/compound_event_filter.cc b/chromium/ui/views/corewm/compound_event_filter.cc index 91c15205f0d..1d4387b162e 100644 --- a/chromium/ui/views/corewm/compound_event_filter.cc +++ b/chromium/ui/views/corewm/compound_event_filter.cc @@ -5,6 +5,7 @@ #include "ui/views/corewm/compound_event_filter.h" #include "base/containers/hash_tables.h" +#include "base/logging.h" #include "ui/aura/client/activation_client.h" #include "ui/aura/client/cursor_client.h" #include "ui/aura/client/drag_drop_client.h" @@ -13,8 +14,8 @@ #include "ui/aura/root_window.h" #include "ui/aura/window_delegate.h" #include "ui/aura/window_tracker.h" -#include "ui/base/events/event.h" #include "ui/base/hit_test.h" +#include "ui/events/event.h" namespace views { namespace corewm { @@ -183,6 +184,12 @@ void CompoundEventFilter::SetCursorVisibilityOnEvent(aura::Window* target, } else if (!show && !cursor_hidden_by_filter_) { cursor_hidden_by_filter_ = true; client->HideCursor(); + } else if (show && !client->IsCursorVisible() && !client->IsCursorLocked()) { + // TODO(tdanderson): Remove this temporary logging once the issues related + // to a disappearing mouse cursor on the Pixel login screen / Pixel + // wakeup have been resolved. See crbug.com/275826. + LOG(ERROR) << "Event of type " << event->type() << " did not show cursor." + << " Mouse enabled state is " << client->IsMouseEventsEnabled(); } } diff --git a/chromium/ui/views/corewm/compound_event_filter.h b/chromium/ui/views/corewm/compound_event_filter.h index e9c927f941a..15445cddb45 100644 --- a/chromium/ui/views/corewm/compound_event_filter.h +++ b/chromium/ui/views/corewm/compound_event_filter.h @@ -7,8 +7,8 @@ #include "base/compiler_specific.h" #include "base/observer_list.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_handler.h" +#include "ui/events/event.h" +#include "ui/events/event_handler.h" #include "ui/gfx/native_widget_types.h" #include "ui/views/views_export.h" diff --git a/chromium/ui/views/corewm/compound_event_filter_unittest.cc b/chromium/ui/views/corewm/compound_event_filter_unittest.cc index 07624c91ee0..a6569e2be40 100644 --- a/chromium/ui/views/corewm/compound_event_filter_unittest.cc +++ b/chromium/ui/views/corewm/compound_event_filter_unittest.cc @@ -13,8 +13,8 @@ #include "ui/aura/test/test_activation_client.h" #include "ui/aura/test/test_cursor_client.h" #include "ui/aura/test/test_windows.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_utils.h" +#include "ui/events/event.h" +#include "ui/events/event_utils.h" namespace { diff --git a/chromium/ui/views/corewm/corewm_switches.cc b/chromium/ui/views/corewm/corewm_switches.cc index 450738e6a21..8f0dd82a6a9 100644 --- a/chromium/ui/views/corewm/corewm_switches.cc +++ b/chromium/ui/views/corewm/corewm_switches.cc @@ -10,14 +10,6 @@ namespace views { namespace corewm { namespace switches { -// When set uses the old ActivationController/FocusManager instead of the new -// CoreWM FocusController. -const char kDisableFocusController[] = "disable-focus-controller"; - -// When set uses the FocusController in desktop mode. -const char kDisableFocusControllerOnDesktop[] = - "disable-focus-controller-on-desktop"; - const char kNoDropShadows[] = "aura-no-shadows"; // If present animations are disabled. @@ -25,16 +17,5 @@ const char kWindowAnimationsDisabled[] = "views-corewm-window-animations-disabled"; } // namespace switches - -bool UseFocusController() { - return !CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableFocusController); -} - -bool UseFocusControllerOnDesktop() { - return !CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableFocusControllerOnDesktop); -} - } // namespace corewm } // namespace views diff --git a/chromium/ui/views/corewm/corewm_switches.h b/chromium/ui/views/corewm/corewm_switches.h index a78088cd7ca..63c5251745d 100644 --- a/chromium/ui/views/corewm/corewm_switches.h +++ b/chromium/ui/views/corewm/corewm_switches.h @@ -21,14 +21,6 @@ VIEWS_EXPORT extern const char kNoDropShadows[]; VIEWS_EXPORT extern const char kWindowAnimationsDisabled[]; } // namespace switches - -// Returns true if the new FocusController should be used as the -// Activation/FocusClient. -VIEWS_EXPORT bool UseFocusController(); - -// Same as above but for Desktop mode. -VIEWS_EXPORT bool UseFocusControllerOnDesktop(); - } // namespace corewm } // namespace views diff --git a/chromium/ui/views/corewm/cursor_manager.cc b/chromium/ui/views/corewm/cursor_manager.cc index 5c4dc81fc7c..97a19ba93c3 100644 --- a/chromium/ui/views/corewm/cursor_manager.cc +++ b/chromium/ui/views/corewm/cursor_manager.cc @@ -23,6 +23,7 @@ class CursorState { : cursor_(ui::kCursorNone), visible_(true), scale_(1.f), + cursor_set_(ui::CURSOR_SET_NORMAL), mouse_events_enabled_(true), visible_on_mouse_events_enabled_(true) { } @@ -42,6 +43,11 @@ class CursorState { scale_ = scale; } + ui::CursorSetType cursor_set() const { return cursor_set_; } + void set_cursor_set(ui::CursorSetType cursor_set) { + cursor_set_ = cursor_set; + } + bool mouse_events_enabled() const { return mouse_events_enabled_; } void SetMouseEventsEnabled(bool enabled) { if (mouse_events_enabled_ == enabled) @@ -61,6 +67,7 @@ class CursorState { gfx::NativeCursor cursor_; bool visible_; float scale_; + ui::CursorSetType cursor_set_; bool mouse_events_enabled_; // The visibility to set when mouse events are enabled. @@ -119,10 +126,20 @@ void CursorManager::SetScale(float scale) { delegate_->SetScale(state_on_unlock_->scale(), this); } +void CursorManager::SetCursorSet(ui::CursorSetType cursor_set) { + state_on_unlock_->set_cursor_set(cursor_set); + if (GetCurrentCursorSet() != state_on_unlock_->cursor_set()) + delegate_->SetCursorSet(state_on_unlock_->cursor_set(), this); +} + float CursorManager::GetCurrentScale() const { return current_state_->scale(); } +ui::CursorSetType CursorManager::GetCurrentCursorSet() const { + return current_state_->cursor_set(); +} + void CursorManager::EnableMouseEvents() { state_on_unlock_->SetMouseEventsEnabled(true); if (cursor_lock_count_ == 0 && @@ -172,6 +189,10 @@ void CursorManager::UnlockCursor() { } } +bool CursorManager::IsCursorLocked() const { + return cursor_lock_count_ > 0; +} + void CursorManager::AddObserver( aura::client::CursorClientObserver* observer) { observers_.AddObserver(observer); @@ -208,6 +229,10 @@ void CursorManager::CommitScale(float scale) { current_state_->set_scale(scale); } +void CursorManager::CommitCursorSet(ui::CursorSetType cursor_set) { + current_state_->set_cursor_set(cursor_set); +} + void CursorManager::CommitMouseEventsEnabled(bool enabled) { current_state_->SetMouseEventsEnabled(enabled); } diff --git a/chromium/ui/views/corewm/cursor_manager.h b/chromium/ui/views/corewm/cursor_manager.h index 9e3164079df..1706ed8f7af 100644 --- a/chromium/ui/views/corewm/cursor_manager.h +++ b/chromium/ui/views/corewm/cursor_manager.h @@ -10,6 +10,7 @@ #include "base/memory/scoped_ptr.h" #include "base/observer_list.h" #include "ui/aura/client/cursor_client.h" +#include "ui/base/cursor/cursor.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/point.h" #include "ui/views/corewm/native_cursor_manager_delegate.h" @@ -38,8 +39,6 @@ class VIEWS_EXPORT CursorManager : public aura::client::CursorClient, CursorManager(scoped_ptr<NativeCursorManager> delegate); virtual ~CursorManager(); - bool is_cursor_locked() const { return cursor_lock_count_ > 0; } - // Overridden from aura::client::CursorClient: virtual void SetCursor(gfx::NativeCursor) OVERRIDE; virtual void ShowCursor() OVERRIDE; @@ -47,12 +46,15 @@ class VIEWS_EXPORT CursorManager : public aura::client::CursorClient, virtual bool IsCursorVisible() const OVERRIDE; virtual void SetScale(float scale) OVERRIDE; virtual float GetCurrentScale() const OVERRIDE; + virtual void SetCursorSet(ui::CursorSetType cursor_set) OVERRIDE; + virtual ui::CursorSetType GetCurrentCursorSet() const OVERRIDE; virtual void EnableMouseEvents() OVERRIDE; virtual void DisableMouseEvents() OVERRIDE; virtual bool IsMouseEventsEnabled() const OVERRIDE; virtual void SetDisplay(const gfx::Display& display) OVERRIDE; virtual void LockCursor() OVERRIDE; virtual void UnlockCursor() OVERRIDE; + virtual bool IsCursorLocked() const OVERRIDE; virtual void AddObserver( aura::client::CursorClientObserver* observer) OVERRIDE; virtual void RemoveObserver( @@ -66,6 +68,7 @@ class VIEWS_EXPORT CursorManager : public aura::client::CursorClient, virtual void CommitCursor(gfx::NativeCursor cursor) OVERRIDE; virtual void CommitVisibility(bool visible) OVERRIDE; virtual void CommitScale(float scale) OVERRIDE; + virtual void CommitCursorSet(ui::CursorSetType cursor_set) OVERRIDE; virtual void CommitMouseEventsEnabled(bool enabled) OVERRIDE; scoped_ptr<NativeCursorManager> delegate_; diff --git a/chromium/ui/views/corewm/cursor_manager_unittest.cc b/chromium/ui/views/corewm/cursor_manager_unittest.cc index 650d5b842b5..1e6a1650907 100644 --- a/chromium/ui/views/corewm/cursor_manager_unittest.cc +++ b/chromium/ui/views/corewm/cursor_manager_unittest.cc @@ -38,6 +38,12 @@ class TestingCursorManager : public views::corewm::NativeCursorManager { delegate->CommitMouseEventsEnabled(enabled); } + virtual void SetCursorSet( + ui::CursorSetType cursor_set, + views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE { + delegate->CommitCursorSet(cursor_set); + } + virtual void SetScale( float scale, views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE { @@ -186,6 +192,19 @@ TEST_F(CursorManagerTest, EnableDisableMouseEvents) { EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled()); } +TEST_F(CursorManagerTest, SetCursorSet) { + EXPECT_EQ(ui::CURSOR_SET_NORMAL, cursor_manager_.GetCurrentCursorSet()); + + cursor_manager_.SetCursorSet(ui::CURSOR_SET_NORMAL); + EXPECT_EQ(ui::CURSOR_SET_NORMAL, cursor_manager_.GetCurrentCursorSet()); + + cursor_manager_.SetCursorSet(ui::CURSOR_SET_LARGE); + EXPECT_EQ(ui::CURSOR_SET_LARGE, cursor_manager_.GetCurrentCursorSet()); + + cursor_manager_.SetCursorSet(ui::CURSOR_SET_NORMAL); + EXPECT_EQ(ui::CURSOR_SET_NORMAL, cursor_manager_.GetCurrentCursorSet()); +} + TEST_F(CursorManagerTest, SetScale) { EXPECT_EQ(1.f, cursor_manager_.GetCurrentScale()); cursor_manager_.SetScale(2.f); diff --git a/chromium/ui/views/corewm/desktop_capture_controller_unittest.cc b/chromium/ui/views/corewm/desktop_capture_controller_unittest.cc new file mode 100644 index 00000000000..4d50f68e291 --- /dev/null +++ b/chromium/ui/views/corewm/desktop_capture_controller_unittest.cc @@ -0,0 +1,176 @@ +// Copyright (c) 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 "ui/views/corewm/capture_controller.h" + +#include "base/logging.h" +#include "ui/aura/env.h" +#include "ui/aura/root_window.h" +#include "ui/aura/test/test_window_delegate.h" +#include "ui/events/event.h" +#include "ui/views/test/views_test_base.h" +#include "ui/views/view.h" +#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" +#include "ui/views/widget/desktop_aura/desktop_screen_position_client.h" +#include "ui/views/widget/root_view.h" +#include "ui/views/widget/widget.h" + +namespace views { + +typedef ViewsTestBase DesktopCaptureControllerTest; + +// NOTE: these tests do native capture, so they have to be in +// interactive_ui_tests. + +// This class provides functionality to verify whether the View instance +// received the gesture event. +class DesktopViewInputTest : public View { + public: + DesktopViewInputTest() + : received_gesture_event_(false) {} + + virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { + received_gesture_event_ = true; + return View::OnGestureEvent(event); + } + + // Resets state maintained by this class. + void Reset() { + received_gesture_event_ = false; + } + + bool received_gesture_event() const { return received_gesture_event_; } + + private: + bool received_gesture_event_; + + DISALLOW_COPY_AND_ASSIGN(DesktopViewInputTest); +}; + +// Tests aura::Window capture and whether gesture events are sent to the window +// which has capture. +// The test case creates two visible widgets and sets capture to the underlying +// aura::Windows one by one. It then sends a gesture event and validates whether +// the window which had capture receives the gesture. +TEST_F(DesktopCaptureControllerTest, CaptureWindowInputEventTest) { + scoped_ptr<aura::client::ScreenPositionClient> desktop_position_client1; + scoped_ptr<aura::client::ScreenPositionClient> desktop_position_client2; + + scoped_ptr<Widget> widget1(new Widget()); + Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); + scoped_ptr<corewm::ScopedCaptureClient> scoped_capture_client( + new corewm::ScopedCaptureClient(params.context->GetRootWindow())); + aura::client::CaptureClient* capture_client = + scoped_capture_client->capture_client(); + params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + params.bounds = gfx::Rect(50, 50, 650, 650); + widget1->Init(params); + internal::RootView* root1 = + static_cast<internal::RootView*>(widget1->GetRootView()); + + desktop_position_client1.reset(new DesktopScreenPositionClient()); + aura::client::SetScreenPositionClient( + widget1->GetNativeView()->GetRootWindow(), + desktop_position_client1.get()); + + DesktopViewInputTest* v1 = new DesktopViewInputTest(); + v1->SetBoundsRect(gfx::Rect(0, 0, 300, 300)); + root1->AddChildView(v1); + widget1->Show(); + + scoped_ptr<Widget> widget2(new Widget()); + + params = CreateParams(Widget::InitParams::TYPE_POPUP); + params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + params.bounds = gfx::Rect(50, 50, 650, 650); + widget2->Init(params); + + internal::RootView* root2 = + static_cast<internal::RootView*>(widget2->GetRootView()); + desktop_position_client2.reset(new DesktopScreenPositionClient()); + aura::client::SetScreenPositionClient( + widget2->GetNativeView()->GetRootWindow(), + desktop_position_client2.get()); + + DesktopViewInputTest* v2 = new DesktopViewInputTest(); + v2->SetBoundsRect(gfx::Rect(0, 0, 300, 300)); + root2->AddChildView(v2); + widget2->Show(); + + EXPECT_FALSE(widget1->GetNativeView()->HasCapture()); + EXPECT_FALSE(widget2->GetNativeView()->HasCapture()); + EXPECT_EQ(reinterpret_cast<aura::Window*>(0), + capture_client->GetCaptureWindow()); + + widget1->GetNativeView()->SetCapture(); + EXPECT_TRUE(widget1->GetNativeView()->HasCapture()); + EXPECT_FALSE(widget2->GetNativeView()->HasCapture()); + EXPECT_EQ(capture_client->GetCaptureWindow(), widget1->GetNativeView()); + + ui::GestureEvent g1(ui::ET_GESTURE_LONG_PRESS, 80, 80, 0, + base::TimeDelta(), + ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS, + 0.0f, 0.0f), 0); + root1->DispatchGestureEvent(&g1); + EXPECT_TRUE(v1->received_gesture_event()); + EXPECT_FALSE(v2->received_gesture_event()); + v1->Reset(); + v2->Reset(); + + widget2->GetNativeView()->SetCapture(); + + EXPECT_FALSE(widget1->GetNativeView()->HasCapture()); + EXPECT_TRUE(widget2->GetNativeView()->HasCapture()); + EXPECT_EQ(capture_client->GetCaptureWindow(), widget2->GetNativeView()); + + root2->DispatchGestureEvent(&g1); + EXPECT_TRUE(v2->received_gesture_event()); + EXPECT_FALSE(v1->received_gesture_event()); + + widget1->CloseNow(); + widget2->CloseNow(); + RunPendingMessages(); +} + +// crbug.com/295342 +#if defined(OS_WIN) +#define MAYBE_TransferOnCapture DISABLED_TransferOnCapture +#else +#define MAYBE_TransferOnCapture TransferOnCapture +#endif +// Verifies aura::RootWindow is correctly notified on capture changes. +TEST_F(DesktopCaptureControllerTest, MAYBE_TransferOnCapture) { + Widget widget1; + Widget::InitParams params1 = + CreateParams(views::Widget::InitParams::TYPE_WINDOW); + params1.native_widget = new DesktopNativeWidgetAura(&widget1); + params1.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + widget1.Init(params1); + widget1.Show(); + + Widget widget2; + Widget::InitParams params2 = + CreateParams(views::Widget::InitParams::TYPE_WINDOW); + params2.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + params2.native_widget = new DesktopNativeWidgetAura(&widget2); + widget2.Init(params2); + widget2.Show(); + + // Set capture to |widget2|, then |widget1| and lastly release capture. + aura::Env::GetInstance()->set_mouse_button_flags(1); + widget2.SetCapture(widget2.GetRootView()); + widget1.SetCapture(widget1.GetRootView()); + widget1.ReleaseCapture(); + // Widget1's RootWindow should still have a non-NULL |mouse_moved_handler_| + // (since it contains the view that had capture). OTOH Widget2 doesn't contain + // the Window that had capture and so its |mouse_moved_handler_| should be + // NULL. + EXPECT_NE(static_cast<aura::Window*>(NULL), + widget1.GetNativeView()->GetRootWindow()->mouse_moved_handler()); + EXPECT_EQ(static_cast<aura::Window*>(NULL), + widget2.GetNativeView()->GetRootWindow()->mouse_moved_handler()); + aura::Env::GetInstance()->set_mouse_button_flags(0); +} + +} // namespace views diff --git a/chromium/ui/views/corewm/focus_controller.cc b/chromium/ui/views/corewm/focus_controller.cc index fc9c3136dfa..a5fe9c3a7a9 100644 --- a/chromium/ui/views/corewm/focus_controller.cc +++ b/chromium/ui/views/corewm/focus_controller.cc @@ -10,7 +10,7 @@ #include "ui/aura/client/capture_client.h" #include "ui/aura/client/focus_change_observer.h" #include "ui/aura/env.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" #include "ui/views/corewm/focus_rules.h" namespace views { @@ -130,9 +130,12 @@ void FocusController::FocusWindow(aura::Window* window) { return; } - // We should not be messing with the focus if the window has capture. - if (window && (aura::client::GetCaptureWindow(window) == window)) + // We should not be messing with the focus if the window has capture, unless + // no has focus. + if (window && (aura::client::GetCaptureWindow(window) == window) && + focused_window_) { return; + } // Focusing a window also activates its containing activatable window. Note // that the rules could redirect activation activation and/or focus. diff --git a/chromium/ui/views/corewm/focus_controller_unittest.cc b/chromium/ui/views/corewm/focus_controller_unittest.cc index 62062f875c4..964fd588b48 100644 --- a/chromium/ui/views/corewm/focus_controller_unittest.cc +++ b/chromium/ui/views/corewm/focus_controller_unittest.cc @@ -18,7 +18,7 @@ #include "ui/aura/test/test_windows.h" #include "ui/aura/window.h" #include "ui/aura/window_tracker.h" -#include "ui/base/events/event_handler.h" +#include "ui/events/event_handler.h" #include "ui/views/corewm/base_focus_rules.h" namespace views { @@ -268,7 +268,8 @@ class FocusControllerTestBase : public aura::test::AuraTestBase { return aura::client::GetFocusClient(root_window())->GetFocusedWindow(); } int GetFocusedWindowId() { - return GetFocusedWindow()->id(); + aura::Window* focused_window = GetFocusedWindow(); + return focused_window ? focused_window->id() : -1; } void ActivateWindow(aura::Window* window) { aura::client::GetActivationClient(root_window())->ActivateWindow(window); @@ -303,6 +304,7 @@ class FocusControllerTestBase : public aura::test::AuraTestBase { virtual void ShiftFocusOnActivationDueToHide() {} virtual void NoShiftActiveOnActivation() {} virtual void NoFocusChangeOnClickOnCaptureWindow() {} + virtual void ChangeFocusWhenNothingFocusedAndCaptured() {} private: scoped_ptr<FocusController> focus_controller_; @@ -598,6 +600,24 @@ class FocusControllerDirectTestBase : public FocusControllerTestBase { aura::client::GetCaptureClient(root_window())->ReleaseCapture(w2); } + // Verifies focus change is honored while capture held. + virtual void ChangeFocusWhenNothingFocusedAndCaptured() OVERRIDE { + scoped_ptr<aura::client::DefaultCaptureClient> capture_client( + new aura::client::DefaultCaptureClient(root_window())); + aura::Window* w1 = root_window()->GetChildById(1); + aura::client::GetCaptureClient(root_window())->SetCapture(w1); + + EXPECT_EQ(-1, GetActiveWindowId()); + EXPECT_EQ(-1, GetFocusedWindowId()); + + FocusWindowById(1); + + EXPECT_EQ(1, GetActiveWindowId()); + EXPECT_EQ(1, GetFocusedWindowId()); + + aura::client::GetCaptureClient(root_window())->ReleaseCapture(w1); + } + private: DISALLOW_COPY_AND_ASSIGN(FocusControllerDirectTestBase); }; @@ -996,5 +1016,8 @@ DIRECT_FOCUS_CHANGE_TESTS(NoShiftActiveOnActivation); // Clicking on a window which has capture should not result in a focus change. DIRECT_FOCUS_CHANGE_TESTS(NoFocusChangeOnClickOnCaptureWindow); +FOCUS_CONTROLLER_TEST(FocusControllerApiTest, + ChangeFocusWhenNothingFocusedAndCaptured); + } // namespace corewm } // namespace views diff --git a/chromium/ui/views/corewm/input_method_event_filter.cc b/chromium/ui/views/corewm/input_method_event_filter.cc index f8e964735a9..cfdab6b7c67 100644 --- a/chromium/ui/views/corewm/input_method_event_filter.cc +++ b/chromium/ui/views/corewm/input_method_event_filter.cc @@ -6,9 +6,9 @@ #include "ui/aura/client/aura_constants.h" #include "ui/aura/root_window.h" -#include "ui/base/events/event.h" #include "ui/base/ime/input_method.h" #include "ui/base/ime/input_method_factory.h" +#include "ui/events/event.h" namespace views { namespace corewm { diff --git a/chromium/ui/views/corewm/input_method_event_filter.h b/chromium/ui/views/corewm/input_method_event_filter.h index 56ef40e468c..cb1fae489c5 100644 --- a/chromium/ui/views/corewm/input_method_event_filter.h +++ b/chromium/ui/views/corewm/input_method_event_filter.h @@ -8,8 +8,8 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" -#include "ui/base/events/event_handler.h" #include "ui/base/ime/input_method_delegate.h" +#include "ui/events/event_handler.h" #include "ui/gfx/native_widget_types.h" #include "ui/views/views_export.h" diff --git a/chromium/ui/views/corewm/native_cursor_manager.h b/chromium/ui/views/corewm/native_cursor_manager.h index c38fb344052..75e4c8580a5 100644 --- a/chromium/ui/views/corewm/native_cursor_manager.h +++ b/chromium/ui/views/corewm/native_cursor_manager.h @@ -48,6 +48,11 @@ class VIEWS_EXPORT NativeCursorManager { float scale, views::corewm::NativeCursorManagerDelegate* delegate) = 0; + // A request to set the scale of the cursor icon. + virtual void SetCursorSet( + ui::CursorSetType cursor_set, + views::corewm::NativeCursorManagerDelegate* delegate) = 0; + // A request to set whether mouse events are disabled. At minimum, // implementer should call NativeCursorManagerDelegate:: // CommitMouseEventsEnabled() with whether mouse events are actually enabled. diff --git a/chromium/ui/views/corewm/native_cursor_manager_delegate.h b/chromium/ui/views/corewm/native_cursor_manager_delegate.h index 1e6d46a83de..ea3788f883f 100644 --- a/chromium/ui/views/corewm/native_cursor_manager_delegate.h +++ b/chromium/ui/views/corewm/native_cursor_manager_delegate.h @@ -5,6 +5,7 @@ #ifndef UI_VIEWS_COREWM_NATIVE_CURSOR_MANAGER_DELEGATE_H_ #define UI_VIEWS_COREWM_NATIVE_CURSOR_MANAGER_DELEGATE_H_ +#include "ui/base/cursor/cursor.h" #include "ui/gfx/native_widget_types.h" #include "ui/views/views_export.h" @@ -21,11 +22,13 @@ class VIEWS_EXPORT NativeCursorManagerDelegate { virtual gfx::NativeCursor GetCurrentCursor() const = 0; virtual bool GetCurrentVisibility() const = 0; virtual float GetCurrentScale() const = 0; + virtual ui::CursorSetType GetCurrentCursorSet() const = 0; virtual bool GetMouseEventsEnabled() const = 0; virtual void CommitCursor(gfx::NativeCursor cursor) = 0; virtual void CommitVisibility(bool visible) = 0; virtual void CommitScale(float scale) = 0; + virtual void CommitCursorSet(ui::CursorSetType cursor_set) = 0; virtual void CommitMouseEventsEnabled(bool enabled) = 0; }; diff --git a/chromium/ui/views/corewm/tooltip_controller.cc b/chromium/ui/views/corewm/tooltip_controller.cc index 7e3d262b4f4..54b4f7ae04a 100644 --- a/chromium/ui/views/corewm/tooltip_controller.cc +++ b/chromium/ui/views/corewm/tooltip_controller.cc @@ -15,13 +15,13 @@ #include "ui/aura/env.h" #include "ui/aura/root_window.h" #include "ui/aura/window.h" -#include "ui/base/events/event.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/base/text/text_elider.h" +#include "ui/events/event.h" #include "ui/gfx/font.h" #include "ui/gfx/point.h" #include "ui/gfx/rect.h" #include "ui/gfx/screen.h" +#include "ui/gfx/text_elider.h" #include "ui/views/background.h" #include "ui/views/border.h" #include "ui/views/controls/label.h" @@ -102,10 +102,7 @@ class TooltipController::Tooltip : public views::WidgetObserver { } virtual ~Tooltip() { - if (widget_) { - widget_->RemoveObserver(this); - widget_->Close(); - } + DestroyWidget(); } // Updates the text on the tooltip and resizes to fit. @@ -126,7 +123,7 @@ class TooltipController::Tooltip : public views::WidgetObserver { width += 2 * kTooltipBorderWidth; height += 2 * kTooltipBorderWidth; } - CreateWidgetIfNecessary(window); + GetWidgetForWindow(window); SetTooltipBounds(location, width, height); } @@ -180,14 +177,30 @@ class TooltipController::Tooltip : public views::WidgetObserver { widget_->SetBounds(tooltip_rect); } - void CreateWidgetIfNecessary(aura::Window* tooltip_window) { - if (widget_) - return; + void GetWidgetForWindow(aura::Window* tooltip_window) { + if (widget_) { + // If the window for which the tooltip is being displayed changes and if + // the tooltip window and the tooltip widget belong to different + // rootwindows then we need to recreate the tooltip widget under the + // active root window hierarchy to get it to display. + if (widget_->GetNativeWindow()->GetRootWindow() == + tooltip_window->GetRootWindow()) + return; + DestroyWidget(); + } widget_ = CreateTooltip(tooltip_window); widget_->SetContentsView(&label_); widget_->AddObserver(this); } + void DestroyWidget() { + if (widget_) { + widget_->RemoveObserver(this); + widget_->Close(); + widget_ = NULL; + } + } + views::Label label_; TooltipController* controller_; views::Widget* widget_; @@ -256,13 +269,17 @@ void TooltipController::OnKeyEvent(ui::KeyEvent* event) { void TooltipController::OnMouseEvent(ui::MouseEvent* event) { aura::Window* target = static_cast<aura::Window*>(event->target()); switch (event->type()) { + case ui::ET_MOUSE_EXITED: + target = NULL; + // Fall through. case ui::ET_MOUSE_MOVED: case ui::ET_MOUSE_DRAGGED: if (tooltip_window_ != target) { if (tooltip_window_) tooltip_window_->RemoveObserver(this); tooltip_window_ = target; - tooltip_window_->AddObserver(this); + if (tooltip_window_) + tooltip_window_->AddObserver(this); } curr_mouse_loc_ = event->location(); if (tooltip_timer_.IsRunning()) @@ -403,7 +420,7 @@ void TooltipController::TrimTooltipToFit(int max_width, if (result_lines.size() > kMaxLines) { result_lines.resize(kMaxLines); // Add ellipses character to last line. - result_lines[kMaxLines - 1] = ui::TruncateString( + result_lines[kMaxLines - 1] = gfx::TruncateString( result_lines.back(), result_lines.back().length() - 1); } *line_count = result_lines.size(); @@ -420,7 +437,8 @@ void TooltipController::TrimTooltipToFit(int max_width, // case, we simply truncate at available_width and add ellipses at the end. if (line_width > available_width) { *width = available_width; - result.append(ui::ElideText(*l, font, available_width, ui::ELIDE_AT_END)); + result.append(gfx::ElideText(*l, font, available_width, + gfx::ELIDE_AT_END)); } else { *width = std::max(*width, line_width); result.append(*l); diff --git a/chromium/ui/views/corewm/tooltip_controller.h b/chromium/ui/views/corewm/tooltip_controller.h index cc641d05ebc..9cd04d3cb8a 100644 --- a/chromium/ui/views/corewm/tooltip_controller.h +++ b/chromium/ui/views/corewm/tooltip_controller.h @@ -12,7 +12,7 @@ #include "base/timer/timer.h" #include "ui/aura/client/tooltip_client.h" #include "ui/aura/window_observer.h" -#include "ui/base/events/event_handler.h" +#include "ui/events/event_handler.h" #include "ui/gfx/point.h" #include "ui/gfx/screen_type_delegate.h" #include "ui/views/views_export.h" diff --git a/chromium/ui/views/corewm/tooltip_controller_unittest.cc b/chromium/ui/views/corewm/tooltip_controller_unittest.cc index 5cb3fe6b9db..efe561d7a5b 100644 --- a/chromium/ui/views/corewm/tooltip_controller_unittest.cc +++ b/chromium/ui/views/corewm/tooltip_controller_unittest.cc @@ -7,15 +7,16 @@ #include "base/strings/utf_string_conversions.h" #include "ui/aura/client/cursor_client.h" #include "ui/aura/client/tooltip_client.h" +#include "ui/aura/client/window_types.h" #include "ui/aura/env.h" #include "ui/aura/root_window.h" #include "ui/aura/test/aura_test_base.h" #include "ui/aura/test/event_generator.h" #include "ui/aura/window.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/base/text/text_elider.h" #include "ui/gfx/font.h" #include "ui/gfx/point.h" +#include "ui/gfx/text_elider.h" #include "ui/views/corewm/tooltip_controller_test_helper.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" @@ -274,8 +275,8 @@ TEST_F(TooltipControllerTest, TrimTooltipToFitTests) { max_width, &tooltip, &width, &line_count); EXPECT_NEAR(max_pixel_width, width, 5); EXPECT_EQ(1, line_count); - EXPECT_EQ(ui::ElideText(UTF8ToUTF16(std::string('a', max_pixel_width)), font, - max_pixel_width, ui::ELIDE_AT_END), tooltip); + EXPECT_EQ(gfx::ElideText(UTF8ToUTF16(std::string('a', max_pixel_width)), font, + max_pixel_width, gfx::ELIDE_AT_END), tooltip); #endif // Normal small tooltip should stay as is. @@ -409,6 +410,138 @@ TEST_F(TooltipControllerTest, TooltipHidesOnTimeoutAndStaysHiddenUntilChange) { EXPECT_EQ(window, helper_->GetTooltipWindow()); } +// Verifies a mouse exit event hides the tooltips. +TEST_F(TooltipControllerTest, HideOnExit) { + view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text")); + generator_->MoveMouseToCenterOf(GetWindow()); + string16 expected_tooltip = ASCIIToUTF16("Tooltip Text"); + EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(GetWindow())); + EXPECT_EQ(string16(), helper_->GetTooltipText()); + EXPECT_EQ(GetWindow(), helper_->GetTooltipWindow()); + + // Fire tooltip timer so tooltip becomes visible. + helper_->FireTooltipTimer(); + + EXPECT_TRUE(helper_->IsTooltipVisible()); + generator_->SendMouseExit(); + EXPECT_FALSE(helper_->IsTooltipVisible()); +} + +#if !defined(OS_CHROMEOS) +// This test creates two top level windows and verifies that the tooltip +// displays correctly when mouse moves are dispatched to these windows. +// Additionally it also verifies that the tooltip is reparented to the new +// window when mouse moves are dispatched to it. +TEST_F(TooltipControllerTest, TooltipsInMultipleRootWindows) { + view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text For RootWindow1")); + EXPECT_EQ(string16(), helper_->GetTooltipText()); + EXPECT_EQ(NULL, helper_->GetTooltipWindow()); + + aura::Window* window = GetWindow(); + aura::RootWindow* root_window = GetRootWindow(); + + // Fire tooltip timer so tooltip becomes visible. + generator_->MoveMouseRelativeTo(window, view_->bounds().CenterPoint()); + helper_->FireTooltipTimer(); + EXPECT_TRUE(helper_->IsTooltipVisible()); + for (int i = 0; i < 49; ++i) { + generator_->MoveMouseBy(1, 0); + EXPECT_TRUE(helper_->IsTooltipVisible()); + EXPECT_EQ(window, root_window->GetEventHandlerForPoint( + generator_->current_location())); + string16 expected_tooltip = + ASCIIToUTF16("Tooltip Text For RootWindow1"); + EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window)); + EXPECT_EQ(expected_tooltip, helper_->GetTooltipText()); + EXPECT_EQ(window, helper_->GetTooltipWindow()); + } + + views::Widget* widget2 = CreateWidget(NULL); + widget2->SetContentsView(new View); + TooltipTestView* view2 = new TooltipTestView; + widget2->GetContentsView()->AddChildView(view2); + view2->SetBoundsRect(widget2->GetContentsView()->GetLocalBounds()); + helper_.reset(new TooltipControllerTestHelper( + GetController(widget2))); + generator_.reset(new aura::test::EventGenerator( + widget2->GetNativeWindow()->GetRootWindow())); + view2->set_tooltip_text(ASCIIToUTF16("Tooltip Text For RootWindow2")); + + aura::Window* window2 = widget2->GetNativeWindow(); + aura::RootWindow* root_window2 = + widget2->GetNativeWindow()->GetRootWindow(); + // Fire tooltip timer so tooltip becomes visible. + generator_->MoveMouseRelativeTo(window2, view2->bounds().CenterPoint()); + helper_->FireTooltipTimer(); + + EXPECT_NE(root_window, root_window2); + EXPECT_NE(window, window2); + + for (int i = 0; i < 49; ++i) { + generator_->MoveMouseBy(1, 0); + EXPECT_TRUE(helper_->IsTooltipVisible()); + EXPECT_EQ(window2, root_window2->GetEventHandlerForPoint( + generator_->current_location())); + string16 expected_tooltip = ASCIIToUTF16("Tooltip Text For RootWindow2"); + EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window2)); + EXPECT_EQ(expected_tooltip, helper_->GetTooltipText()); + EXPECT_EQ(window2, helper_->GetTooltipWindow()); + } + + bool tooltip_reparented = false; + for (size_t i = 0; i < root_window2->children().size(); ++i) { + if (root_window2->children()[i]->type() == + aura::client::WINDOW_TYPE_TOOLTIP) { + tooltip_reparented = true; + break; + } + } + EXPECT_TRUE(tooltip_reparented); + widget2->Close(); +} + +// This test validates whether the tooltip after becoming visible stays at the +// top of the ZOrder in its root window after activation changes. +TEST_F(TooltipControllerTest, TooltipAtTopOfZOrderAfterActivation) { + view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text")); + EXPECT_EQ(string16(), helper_->GetTooltipText()); + EXPECT_EQ(NULL, helper_->GetTooltipWindow()); + generator_->MoveMouseToCenterOf(GetWindow()); + + EXPECT_EQ(GetWindow(), GetRootWindow()->GetEventHandlerForPoint( + generator_->current_location())); + string16 expected_tooltip = ASCIIToUTF16("Tooltip Text"); + EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(GetWindow())); + EXPECT_EQ(string16(), helper_->GetTooltipText()); + EXPECT_EQ(GetWindow(), helper_->GetTooltipWindow()); + + // Fire tooltip timer so tooltip becomes visible. + helper_->FireTooltipTimer(); + + EXPECT_TRUE(helper_->IsTooltipVisible()); + generator_->MoveMouseBy(1, 0); + + EXPECT_TRUE(helper_->IsTooltipVisible()); + EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(GetWindow())); + EXPECT_EQ(expected_tooltip, helper_->GetTooltipText()); + EXPECT_EQ(GetWindow(), helper_->GetTooltipWindow()); + + // Fake activation loss and gain in the native widget. This should cause a + // ZOrder change which should not affect the position of the tooltip. + DesktopNativeWidgetAura* native_widget = + static_cast<DesktopNativeWidgetAura*>(widget_->native_widget()); + EXPECT_TRUE(native_widget != NULL); + + native_widget->HandleActivationChanged(false); + native_widget->HandleActivationChanged(true); + + EXPECT_EQ( + widget_->GetNativeWindow()->GetRootWindow()->children().back()->type(), + aura::client::WINDOW_TYPE_TOOLTIP); +} + +#endif + } // namespace test } // namespace corewm } // namespace views diff --git a/chromium/ui/views/corewm/window_animations.cc b/chromium/ui/views/corewm/window_animations.cc index f346e22a5b5..84759fe6f6b 100644 --- a/chromium/ui/views/corewm/window_animations.cc +++ b/chromium/ui/views/corewm/window_animations.cc @@ -336,7 +336,7 @@ ui::LayerAnimationElement* CreateGrowShrinkElement( base::TimeDelta::FromMilliseconds( kWindowAnimation_Bounce_DurationMS * kWindowAnimation_Bounce_GrowShrinkDurationPercent / 100))); - transition->set_tween_type(grow ? ui::Tween::EASE_OUT : ui::Tween::EASE_IN); + transition->set_tween_type(grow ? gfx::Tween::EASE_OUT : gfx::Tween::EASE_IN); return transition.release(); } @@ -380,7 +380,7 @@ void AddLayerAnimationsForRotate(aura::Window* window, bool show) { ui::LayerAnimationElement::CreateOpacityElement( show ? kWindowAnimation_ShowOpacity : kWindowAnimation_HideOpacity, duration * kWindowAnimation_Rotate_OpacityDurationPercent / 100)); - opacity->set_tween_type(ui::Tween::EASE_IN_OUT); + opacity->set_tween_type(gfx::Tween::EASE_IN_OUT); window->layer()->GetAnimator()->ScheduleAnimation( new ui::LayerAnimationSequence(opacity.release())); diff --git a/chromium/ui/views/corewm/window_animations_unittest.cc b/chromium/ui/views/corewm/window_animations_unittest.cc index 26fda675af7..5332c7d7d50 100644 --- a/chromium/ui/views/corewm/window_animations_unittest.cc +++ b/chromium/ui/views/corewm/window_animations_unittest.cc @@ -9,10 +9,10 @@ #include "ui/aura/test/aura_test_base.h" #include "ui/aura/test/test_windows.h" #include "ui/aura/window.h" -#include "ui/base/animation/animation_container_element.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animator.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" +#include "ui/gfx/animation/animation_container_element.h" using aura::Window; using ui::Layer; diff --git a/chromium/ui/views/corewm/window_modality_controller.cc b/chromium/ui/views/corewm/window_modality_controller.cc index 6afc7d2c20e..8a3a7ff2040 100644 --- a/chromium/ui/views/corewm/window_modality_controller.cc +++ b/chromium/ui/views/corewm/window_modality_controller.cc @@ -12,8 +12,8 @@ #include "ui/aura/root_window.h" #include "ui/aura/window.h" #include "ui/aura/window_property.h" -#include "ui/base/events/event.h" #include "ui/base/ui_base_types.h" +#include "ui/events/event.h" #include "ui/views/corewm/window_animations.h" #include "ui/views/corewm/window_util.h" diff --git a/chromium/ui/views/corewm/window_modality_controller.h b/chromium/ui/views/corewm/window_modality_controller.h index 4787a97a71f..07fe308e0df 100644 --- a/chromium/ui/views/corewm/window_modality_controller.h +++ b/chromium/ui/views/corewm/window_modality_controller.h @@ -10,7 +10,7 @@ #include "base/compiler_specific.h" #include "ui/aura/env_observer.h" #include "ui/aura/window_observer.h" -#include "ui/base/events/event_handler.h" +#include "ui/events/event_handler.h" #include "ui/views/views_export.h" namespace ui { diff --git a/chromium/ui/views/event_utils.h b/chromium/ui/views/event_utils.h new file mode 100644 index 00000000000..3527c507d4e --- /dev/null +++ b/chromium/ui/views/event_utils.h @@ -0,0 +1,25 @@ +// 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. + +#ifndef UI_VIEWS_EVENT_UTILS_H_ +#define UI_VIEWS_EVENT_UTILS_H_ + +#include "ui/gfx/native_widget_types.h" +#include "ui/views/views_export.h" + +namespace ui { +class LocatedEvent; +} + +namespace views { + +// Reposts a located event natively. Returns false when |event| could not be +// reposted. |event| should be in screen coordinates. |window| is the target +// window that the event will be forwarded to. Only some events are supported. +VIEWS_EXPORT bool RepostLocatedEvent(gfx::NativeWindow window, + const ui::LocatedEvent& event); + +} // namespace views + +#endif // UI_VIEWS_EVENT_UTILS_H_ diff --git a/chromium/ui/views/event_utils_aura.cc b/chromium/ui/views/event_utils_aura.cc new file mode 100644 index 00000000000..54e81246264 --- /dev/null +++ b/chromium/ui/views/event_utils_aura.cc @@ -0,0 +1,51 @@ +// 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 "ui/views/event_utils.h" + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "ui/aura/client/screen_position_client.h" +#include "ui/aura/root_window.h" +#include "ui/events/event.h" +#include "ui/gfx/point.h" + +using aura::client::ScreenPositionClient; + +namespace views { + +bool RepostLocatedEvent(gfx::NativeWindow window, + const ui::LocatedEvent& event) { + if (!window) + return false; + + aura::RootWindow* root_window = window->GetRootWindow(); + + gfx::Point root_loc(event.location()); + ScreenPositionClient* spc = GetScreenPositionClient(root_window); + if (!spc) + return false; + + spc->ConvertPointFromScreen(root_window, &root_loc); + + scoped_ptr<ui::LocatedEvent> relocated; + if (event.IsMouseEvent()) { + const ui::MouseEvent& orig = static_cast<const ui::MouseEvent&>(event); + relocated.reset(new ui::MouseEvent(orig)); + } else if (event.IsGestureEvent()) { + // TODO(rbyers): Gesture event repost is tricky to get right + // crbug.com/170987. + return false; + } else { + NOTREACHED(); + return false; + } + relocated->set_location(root_loc); + relocated->set_root_location(root_loc); + + root_window->RepostEvent(*relocated); + return true; +} + +} // namespace views diff --git a/chromium/ui/views/event_utils_win.cc b/chromium/ui/views/event_utils_win.cc new file mode 100644 index 00000000000..38c05c988fa --- /dev/null +++ b/chromium/ui/views/event_utils_win.cc @@ -0,0 +1,59 @@ +// 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 "ui/views/event_utils.h" + +#include <windowsx.h> + +#include "base/logging.h" +#include "ui/events/event.h" +#include "ui/events/event_constants.h" +#include "ui/gfx/point.h" + +namespace views { + +bool RepostLocatedEvent(gfx::NativeWindow window, + const ui::LocatedEvent& event) { + if (!window) + return false; + + // Determine whether the click was in the client area or not. + // NOTE: WM_NCHITTEST coordinates are relative to the screen. + const gfx::Point screen_loc = event.location(); + LRESULT nc_hit_result = SendMessage(window, WM_NCHITTEST, 0, + MAKELPARAM(screen_loc.x(), + screen_loc.y())); + const bool in_client_area = nc_hit_result == HTCLIENT; + + // TODO(sky): this isn't right. The event to generate should correspond with + // the event we just got. MouseEvent only tells us what is down, which may + // differ. Need to add ability to get changed button from MouseEvent. + int event_type; + int flags = event.flags(); + if (flags & ui::EF_LEFT_MOUSE_BUTTON) { + event_type = in_client_area ? WM_LBUTTONDOWN : WM_NCLBUTTONDOWN; + } else if (flags & ui::EF_MIDDLE_MOUSE_BUTTON) { + event_type = in_client_area ? WM_MBUTTONDOWN : WM_NCMBUTTONDOWN; + } else if (flags & ui::EF_RIGHT_MOUSE_BUTTON) { + event_type = in_client_area ? WM_RBUTTONDOWN : WM_NCRBUTTONDOWN; + } else { + NOTREACHED(); + return false; + } + + int window_x = screen_loc.x(); + int window_y = screen_loc.y(); + if (in_client_area) { + RECT window_bounds; + GetWindowRect(window, &window_bounds); + window_x -= window_bounds.left; + window_y -= window_bounds.top; + } + + WPARAM target = in_client_area ? event.native_event().wParam : nc_hit_result; + PostMessage(window, event_type, target, MAKELPARAM(window_x, window_y)); + return true; +} + +} // namespace views diff --git a/chromium/ui/views/examples/content_client/examples_browser_main_parts.cc b/chromium/ui/views/examples/content_client/examples_browser_main_parts.cc index d357e7699ac..2cea5ef3b31 100644 --- a/chromium/ui/views/examples/content_client/examples_browser_main_parts.cc +++ b/chromium/ui/views/examples/content_client/examples_browser_main_parts.cc @@ -12,7 +12,7 @@ #include "base/threading/thread.h" #include "base/threading/thread_restrictions.h" #include "content/public/common/content_switches.h" -#include "content/shell/shell_browser_context.h" +#include "content/shell/browser/shell_browser_context.h" #include "ui/views/examples/examples_window_with_content.h" #include "ui/views/focus/accelerator_handler.h" #include "ui/views/test/desktop_test_views_delegate.h" diff --git a/chromium/ui/views/examples/example_base.h b/chromium/ui/views/examples/example_base.h index f28fdefba1e..a17cc0d0f91 100644 --- a/chromium/ui/views/examples/example_base.h +++ b/chromium/ui/views/examples/example_base.h @@ -27,6 +27,8 @@ class ExampleBase { protected: explicit ExampleBase(const char* title); + View* container() { return container_; } + // Prints a message in the status area, at the bottom of the window. void PrintStatus(const char* format, ...); diff --git a/chromium/ui/views/examples/multiline_example.cc b/chromium/ui/views/examples/multiline_example.cc index 8d13bf510c6..dd8a633c9ae 100644 --- a/chromium/ui/views/examples/multiline_example.cc +++ b/chromium/ui/views/examples/multiline_example.cc @@ -5,7 +5,7 @@ #include "ui/views/examples/multiline_example.h" #include "base/strings/utf_string_conversions.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" #include "ui/gfx/render_text.h" #include "ui/views/controls/label.h" #include "ui/views/controls/textfield/textfield.h" @@ -18,9 +18,10 @@ namespace examples { // A simple View that hosts a RenderText object. class MultilineExample::RenderTextView : public View { public: - explicit RenderTextView(gfx::RenderText* render_text) - : render_text_(render_text) { + RenderTextView() : render_text_(gfx::RenderText::CreateInstance()) { + render_text_->SetHorizontalAlignment(gfx::ALIGN_CENTER); render_text_->SetColor(SK_ColorBLACK); + render_text_->SetMultiline(true); set_border(Border::CreateSolidBorder(2, SK_ColorGRAY)); } @@ -30,13 +31,40 @@ class MultilineExample::RenderTextView : public View { } virtual gfx::Size GetPreferredSize() OVERRIDE { - return gfx::Size(0, - render_text_->font_list().GetHeight() + GetInsets().height()); + // Turn off multiline mode to get the single-line text size, which is the + // preferred size for this view. + render_text_->SetMultiline(false); + gfx::Size size(render_text_->GetContentWidth(), + render_text_->GetStringSize().height()); + size.Enlarge(GetInsets().width(), GetInsets().height()); + render_text_->SetMultiline(true); + return size; + } + + virtual int GetHeightForWidth(int w) OVERRIDE { + // TODO(ckocagil): Why does this happen? + if (w == 0) + return View::GetHeightForWidth(w); + gfx::Rect rect = render_text_->display_rect(); + rect.set_width(w - GetInsets().width()); + render_text_->SetDisplayRect(rect); + return render_text_->GetStringSize().height() + GetInsets().height(); } void SetText(const string16& new_contents) { + // Color and style the text inside |test_range| to test colors and styles. + gfx::Range test_range(1, 21); + test_range.set_start(std::min(test_range.start(), new_contents.length())); + test_range.set_end(std::min(test_range.end(), new_contents.length())); + render_text_->SetText(new_contents); - SchedulePaint(); + render_text_->SetColor(SK_ColorBLACK); + render_text_->ApplyColor(0xFFFF0000, test_range); + render_text_->SetStyle(gfx::DIAGONAL_STRIKE, false); + render_text_->ApplyStyle(gfx::DIAGONAL_STRIKE, true, test_range); + render_text_->SetStyle(gfx::UNDERLINE, false); + render_text_->ApplyStyle(gfx::UNDERLINE, true, test_range); + InvalidateLayout(); } private: @@ -55,7 +83,8 @@ MultilineExample::MultilineExample() : ExampleBase("Multiline RenderText"), render_text_view_(NULL), label_(NULL), - textfield_(NULL) { + textfield_(NULL), + label_checkbox_(NULL) { } MultilineExample::~MultilineExample() { @@ -65,17 +94,19 @@ void MultilineExample::CreateExampleView(View* container) { const char kTestString[] = "test string asdf 1234 test string asdf 1234 " "test string asdf 1234 test string asdf 1234"; - gfx::RenderText* render_text = gfx::RenderText::CreateInstance(); - render_text->SetText(ASCIIToUTF16(kTestString)); - render_text->SetHorizontalAlignment(gfx::ALIGN_CENTER); - - render_text_view_ = new RenderTextView(render_text); + render_text_view_ = new RenderTextView(); + render_text_view_->SetText(ASCIIToUTF16(kTestString)); label_ = new Label(); label_->SetText(ASCIIToUTF16(kTestString)); label_->SetMultiLine(true); label_->set_border(Border::CreateSolidBorder(2, SK_ColorCYAN)); + label_checkbox_ = new Checkbox(ASCIIToUTF16("views::Label:")); + label_checkbox_->SetChecked(true); + label_checkbox_->set_listener(this); + label_checkbox_->set_request_focus_on_press(false); + textfield_ = new Textfield(); textfield_->SetController(this); textfield_->SetText(ASCIIToUTF16(kTestString)); @@ -84,7 +115,7 @@ void MultilineExample::CreateExampleView(View* container) { container->SetLayoutManager(layout); ColumnSet* column_set = layout->AddColumnSet(0); - column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, + column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0.0f, GridLayout::USE_PREF, 0, 0); column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1.0f, GridLayout::FIXED, 0, 0); @@ -94,7 +125,7 @@ void MultilineExample::CreateExampleView(View* container) { layout->AddView(render_text_view_); layout->StartRow(0, 0); - layout->AddView(new Label(ASCIIToUTF16("views::Label:"))); + layout->AddView(label_checkbox_); layout->AddView(label_); layout->StartRow(0, 0); @@ -105,7 +136,10 @@ void MultilineExample::CreateExampleView(View* container) { void MultilineExample::ContentsChanged(Textfield* sender, const string16& new_contents) { render_text_view_->SetText(new_contents); - label_->SetText(new_contents); + if (label_checkbox_->checked()) + label_->SetText(new_contents); + container()->Layout(); + container()->SchedulePaint(); } bool MultilineExample::HandleKeyEvent(Textfield* sender, @@ -113,5 +147,12 @@ bool MultilineExample::HandleKeyEvent(Textfield* sender, return false; } +void MultilineExample::ButtonPressed(Button* sender, const ui::Event& event) { + DCHECK_EQ(sender, label_checkbox_); + label_->SetText(label_checkbox_->checked() ? textfield_->text() : string16()); + container()->Layout(); + container()->SchedulePaint(); +} + } // namespace examples } // namespace views diff --git a/chromium/ui/views/examples/multiline_example.h b/chromium/ui/views/examples/multiline_example.h index bc5d8c8f548..2757c4ac933 100644 --- a/chromium/ui/views/examples/multiline_example.h +++ b/chromium/ui/views/examples/multiline_example.h @@ -7,6 +7,7 @@ #include "base/compiler_specific.h" #include "base/strings/string16.h" +#include "ui/views/controls/button/checkbox.h" #include "ui/views/controls/textfield/textfield_controller.h" #include "ui/views/examples/example_base.h" @@ -16,9 +17,10 @@ class Label; namespace examples { -// An example that compares the multi-line rendering of different controls. +// An example that compares the multiline rendering of different controls. class MultilineExample : public ExampleBase, - public TextfieldController { + public TextfieldController, + public ButtonListener { public: MultilineExample(); virtual ~MultilineExample(); @@ -26,6 +28,9 @@ class MultilineExample : public ExampleBase, // ExampleBase: virtual void CreateExampleView(View* container) OVERRIDE; + // ButtonListener: + virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE; + private: class RenderTextView; @@ -39,6 +44,9 @@ class MultilineExample : public ExampleBase, Label* label_; Textfield* textfield_; + // Checkbox to enable and disable text rendering in |label_|. + Checkbox* label_checkbox_; + DISALLOW_COPY_AND_ASSIGN(MultilineExample); }; diff --git a/chromium/ui/views/examples/textfield_example.cc b/chromium/ui/views/examples/textfield_example.cc index 55f1c44c7ea..ec18cf74a5b 100644 --- a/chromium/ui/views/examples/textfield_example.cc +++ b/chromium/ui/views/examples/textfield_example.cc @@ -5,8 +5,8 @@ #include "ui/views/examples/textfield_example.h" #include "base/strings/utf_string_conversions.h" -#include "ui/base/events/event.h" -#include "ui/base/range/range.h" +#include "ui/events/event.h" +#include "ui/gfx/range/range.h" #include "ui/gfx/render_text.h" #include "ui/views/controls/button/label_button.h" #include "ui/views/controls/label.h" @@ -121,12 +121,12 @@ void TextfieldExample::ButtonPressed(Button* sender, const ui::Event& event) { if (name_->text().length() >= 5) { size_t fifth = name_->text().length() / 5; - const ui::Range big_range(1 * fifth, 4 * fifth); + const gfx::Range big_range(1 * fifth, 4 * fifth); name_->ApplyStyle(gfx::BOLD, false, big_range); name_->ApplyStyle(gfx::UNDERLINE, true, big_range); name_->ApplyColor(SK_ColorBLUE, big_range); - const ui::Range small_range(2 * fifth, 3 * fifth); + const gfx::Range small_range(2 * fifth, 3 * fifth); name_->ApplyStyle(gfx::ITALIC, true, small_range); name_->ApplyStyle(gfx::UNDERLINE, false, small_range); name_->ApplyStyle(gfx::DIAGONAL_STRIKE, true, small_range); diff --git a/chromium/ui/views/focus/accelerator_handler.h b/chromium/ui/views/focus/accelerator_handler.h index 31ec0b5aff6..29f353e697c 100644 --- a/chromium/ui/views/focus/accelerator_handler.h +++ b/chromium/ui/views/focus/accelerator_handler.h @@ -24,21 +24,13 @@ bool VIEWS_EXPORT DispatchXEvent(XEvent* xevent); // This class delegates the key messages to the associated FocusManager class // for the window that is receiving these messages for accelerator processing. -#if defined(OS_MACOSX) -class VIEWS_EXPORT AcceleratorHandler { -#else class VIEWS_EXPORT AcceleratorHandler : public base::MessageLoop::Dispatcher { -#endif // defined(OS_MACOSX) public: AcceleratorHandler(); // Dispatcher method. This returns true if an accelerator was processed by the // focus manager -#if defined(OS_WIN) || defined(USE_AURA) virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE; -#elif defined(OS_MACOSX) - // TODO(dhollowa): Implement on Mac. http://crbug.com/109946 -#endif private: #if defined(OS_WIN) diff --git a/chromium/ui/views/focus/accelerator_handler_win.cc b/chromium/ui/views/focus/accelerator_handler_win.cc index 7d11c97d28f..ea82daed717 100644 --- a/chromium/ui/views/focus/accelerator_handler_win.cc +++ b/chromium/ui/views/focus/accelerator_handler_win.cc @@ -4,9 +4,9 @@ #include "ui/views/focus/accelerator_handler.h" -#include "ui/base/events/event.h" -#include "ui/base/keycodes/keyboard_code_conversion_win.h" -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/keyboard_code_conversion_win.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/views/focus/focus_manager.h" #include "ui/views/widget/widget.h" diff --git a/chromium/ui/views/focus/focus_manager.cc b/chromium/ui/views/focus/focus_manager.cc index 0a60ee17e8a..429b9ada1b0 100644 --- a/chromium/ui/views/focus/focus_manager.cc +++ b/chromium/ui/views/focus/focus_manager.cc @@ -11,8 +11,8 @@ #include "base/logging.h" #include "build/build_config.h" #include "ui/base/accelerators/accelerator.h" -#include "ui/base/events/event.h" -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/views/focus/focus_manager_delegate.h" #include "ui/views/focus/focus_search.h" #include "ui/views/focus/view_storage.h" @@ -139,7 +139,7 @@ bool FocusManager::ContainsView(View* view) { } void FocusManager::AdvanceFocus(bool reverse) { - View* v = GetNextFocusableView(focused_view_, reverse, false); + View* v = GetNextFocusableView(focused_view_, NULL, reverse, false); // Note: Do not skip this next block when v == focused_view_. If the user // tabs past the last focusable element in a webpage, we'll get here, and if // the TabContentsContainerView is the only focusable view (possible in @@ -219,6 +219,7 @@ bool FocusManager::RotatePaneFocus(Direction direction, } View* FocusManager::GetNextFocusableView(View* original_starting_view, + Widget* starting_widget, bool reverse, bool dont_loop) { FocusTraversable* focus_traversable = NULL; @@ -262,7 +263,8 @@ View* FocusManager::GetNextFocusableView(View* original_starting_view, } } } else { - focus_traversable = widget_->GetFocusTraversable(); + Widget* widget = starting_widget ? starting_widget : widget_; + focus_traversable = widget->GetFocusTraversable(); } // Traverse the FocusTraversable tree down to find the focusable view. @@ -303,9 +305,12 @@ View* FocusManager::GetNextFocusableView(View* original_starting_view, // infinitely looping in empty windows. if (!dont_loop && original_starting_view) { // Easy, just clear the selection and press tab again. - // By calling with NULL as the starting view, we'll start from the - // top_root_view. - return GetNextFocusableView(NULL, reverse, true); + // By calling with NULL as the starting view, we'll start from either + // the starting views widget or |widget_|. + Widget* widget = original_starting_view->GetWidget(); + if (widget->widget_delegate()->ShouldAdvanceFocusToTopLevelWidget()) + widget = widget_; + return GetNextFocusableView(NULL, widget, reverse, true); } } return NULL; @@ -451,7 +456,6 @@ View* FocusManager::FindFocusableView(FocusTraversable* focus_traversable, while (new_focus_traversable) { DCHECK(!v); focus_traversable = new_focus_traversable; - starting_view = new_starting_view; new_focus_traversable = NULL; starting_view = NULL; v = focus_traversable->GetFocusSearch()->FindNextFocusableView( diff --git a/chromium/ui/views/focus/focus_manager.h b/chromium/ui/views/focus/focus_manager.h index 6a17fc2bc1a..be254133826 100644 --- a/chromium/ui/views/focus/focus_manager.h +++ b/chromium/ui/views/focus/focus_manager.h @@ -308,8 +308,16 @@ class VIEWS_EXPORT FocusManager { } private: - // Returns the next focusable view. - View* GetNextFocusableView(View* starting_view, bool reverse, bool dont_loop); + // Returns the next focusable view. Traversal starts at |starting_view|. If + // |starting_view| is NULL |starting_widget| is consuled to determine which + // Widget to start from. See + // WidgetDelegate::ShouldAdvanceFocusToTopLevelWidget() for details. If both + // |starting_view| and |starting_widget| are NULL, traversal starts at + // |widget_|. + View* GetNextFocusableView(View* starting_view, + Widget* starting_widget, + bool reverse, + bool dont_loop); // Returns the focusable view found in the FocusTraversable specified starting // at the specified view. This traverses down along the FocusTraversable diff --git a/chromium/ui/views/focus/focus_manager_unittest.cc b/chromium/ui/views/focus/focus_manager_unittest.cc index 51341f56500..a2c9d48f6fa 100644 --- a/chromium/ui/views/focus/focus_manager_unittest.cc +++ b/chromium/ui/views/focus/focus_manager_unittest.cc @@ -7,7 +7,7 @@ #include "base/strings/utf_string_conversions.h" #include "ui/base/accelerators/accelerator.h" -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/views/accessible_pane_view.h" #include "ui/views/controls/button/label_button.h" #include "ui/views/controls/textfield/textfield.h" @@ -829,4 +829,85 @@ TEST_F(FocusManagerTest, StoreFocusedView) { EXPECT_EQ(&view, GetFocusManager()->GetStoredFocusView()); } +namespace { + +// Trivial WidgetDelegate implementation that allows setting return value of +// ShouldAdvanceFocusToTopLevelWidget(). +class AdvanceFocusWidgetDelegate : public WidgetDelegate { + public: + explicit AdvanceFocusWidgetDelegate(Widget* widget) + : widget_(widget), + should_advance_focus_to_parent_(false) {} + virtual ~AdvanceFocusWidgetDelegate() {} + + void set_should_advance_focus_to_parent(bool value) { + should_advance_focus_to_parent_ = value; + } + + // WidgetDelegate overrides: + virtual bool ShouldAdvanceFocusToTopLevelWidget() const OVERRIDE { + return should_advance_focus_to_parent_; + } + virtual Widget* GetWidget() OVERRIDE { return widget_; } + virtual const Widget* GetWidget() const OVERRIDE { return widget_; } + + private: + Widget* widget_; + bool should_advance_focus_to_parent_; + + DISALLOW_COPY_AND_ASSIGN(AdvanceFocusWidgetDelegate); +}; + +} // namespace + +// Verifies focus wrapping happens in the same widget. +TEST_F(FocusManagerTest, AdvanceFocusStaysInWidget) { + // Add |widget_view| as a child of the Widget. + View* widget_view = new View; + widget_view->set_focusable(true); + widget_view->SetBounds(20, 0, 20, 20); + GetContentsView()->AddChildView(widget_view); + + // Create a widget with two views, focus the second. + scoped_ptr<AdvanceFocusWidgetDelegate> delegate; + Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); + params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + params.child = true; + params.bounds = gfx::Rect(10, 10, 100, 100); + params.parent = GetWidget()->GetNativeView(); + Widget child_widget; + delegate.reset(new AdvanceFocusWidgetDelegate(&child_widget)); + params.delegate = delegate.get(); + child_widget.Init(params); + View* view1 = new View; + view1->set_focusable(true); + view1->SetBounds(0, 0, 20, 20); + View* view2 = new View; + view2->set_focusable(true); + view2->SetBounds(20, 0, 20, 20); + child_widget.client_view()->AddChildView(view1); + child_widget.client_view()->AddChildView(view2); + child_widget.Show(); + view2->RequestFocus(); + EXPECT_EQ(view2, GetFocusManager()->GetFocusedView()); + + // Advance focus backwards, which should focus the first. + GetFocusManager()->AdvanceFocus(false); + EXPECT_EQ(view1, GetFocusManager()->GetFocusedView()); + + // Focus forward to |view2|. + GetFocusManager()->AdvanceFocus(true); + EXPECT_EQ(view2, GetFocusManager()->GetFocusedView()); + + // And forward again, wrapping back to |view1|. + GetFocusManager()->AdvanceFocus(true); + EXPECT_EQ(view1, GetFocusManager()->GetFocusedView()); + + // Allow focus to go to the parent, and focus backwards which should now move + // up |widget_view| (in the parent). + delegate->set_should_advance_focus_to_parent(true); + GetFocusManager()->AdvanceFocus(true); + EXPECT_EQ(widget_view, GetFocusManager()->GetFocusedView()); +} + } // namespace views diff --git a/chromium/ui/views/focus/focus_manager_unittest_win.cc b/chromium/ui/views/focus/focus_manager_unittest_win.cc index 2e7ddc0e3b2..1309ed2d5b9 100644 --- a/chromium/ui/views/focus/focus_manager_unittest_win.cc +++ b/chromium/ui/views/focus/focus_manager_unittest_win.cc @@ -7,7 +7,7 @@ #include "base/memory/scoped_ptr.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" #include "ui/views/controls/button/label_button.h" #include "ui/views/focus/accelerator_handler.h" #include "ui/views/focus/focus_manager_test.h" diff --git a/chromium/ui/views/ime/input_method_base.cc b/chromium/ui/views/ime/input_method_base.cc index 4c4298b7694..784746b7e37 100644 --- a/chromium/ui/views/ime/input_method_base.cc +++ b/chromium/ui/views/ime/input_method_base.cc @@ -5,8 +5,8 @@ #include "ui/views/ime/input_method_base.h" #include "base/logging.h" -#include "ui/base/events/event.h" #include "ui/base/ime/text_input_client.h" +#include "ui/events/event.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" diff --git a/chromium/ui/views/ime/input_method_bridge.cc b/chromium/ui/views/ime/input_method_bridge.cc index 550764757c1..f0ce73b00d9 100644 --- a/chromium/ui/views/ime/input_method_bridge.cc +++ b/chromium/ui/views/ime/input_method_bridge.cc @@ -4,8 +4,8 @@ #include "ui/views/ime/input_method_bridge.h" -#include "ui/base/events/event.h" #include "ui/base/ime/input_method.h" +#include "ui/events/event.h" #include "ui/gfx/rect.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" @@ -16,8 +16,7 @@ InputMethodBridge::InputMethodBridge(internal::InputMethodDelegate* delegate, ui::InputMethod* host, bool shared_input_method) : host_(host), - shared_input_method_(shared_input_method), - context_focused_(false) { + shared_input_method_(shared_input_method) { DCHECK(host_); SetDelegate(delegate); } @@ -29,8 +28,7 @@ InputMethodBridge::~InputMethodBridge() { // this and go into |widget_|. NULL out |widget_| so we don't attempt to use // it. DetachFromWidget(); - if (host_->GetTextInputClient() == this) - host_->SetFocusedTextInputClient(NULL); + host_->DetachTextInputClient(this); } void InputMethodBridge::OnFocus() { @@ -180,33 +178,33 @@ bool InputMethodBridge::HasCompositionText() { return client ? client->HasCompositionText() : false; } -bool InputMethodBridge::GetTextRange(ui::Range* range) { +bool InputMethodBridge::GetTextRange(gfx::Range* range) { TextInputClient* client = GetTextInputClient(); return client ? client->GetTextRange(range) : false; } -bool InputMethodBridge::GetCompositionTextRange(ui::Range* range) { +bool InputMethodBridge::GetCompositionTextRange(gfx::Range* range) { TextInputClient* client = GetTextInputClient(); return client ? client->GetCompositionTextRange(range) : false; } -bool InputMethodBridge::GetSelectionRange(ui::Range* range) { +bool InputMethodBridge::GetSelectionRange(gfx::Range* range) { TextInputClient* client = GetTextInputClient(); return client ? client->GetSelectionRange(range) : false; } -bool InputMethodBridge::SetSelectionRange(const ui::Range& range) { +bool InputMethodBridge::SetSelectionRange(const gfx::Range& range) { TextInputClient* client = GetTextInputClient(); return client ? client->SetSelectionRange(range) : false; } -bool InputMethodBridge::DeleteRange(const ui::Range& range) { +bool InputMethodBridge::DeleteRange(const gfx::Range& range) { TextInputClient* client = GetTextInputClient(); return client ? client->DeleteRange(range) : false; } bool InputMethodBridge::GetTextFromRange( - const ui::Range& range, string16* text) { + const gfx::Range& range, string16* text) { TextInputClient* client = GetTextInputClient(); return client ? client->GetTextFromRange(range, text) : false; } diff --git a/chromium/ui/views/ime/input_method_bridge.h b/chromium/ui/views/ime/input_method_bridge.h index 03ea567aa6d..1a50880154a 100644 --- a/chromium/ui/views/ime/input_method_bridge.h +++ b/chromium/ui/views/ime/input_method_bridge.h @@ -64,13 +64,13 @@ class InputMethodBridge : public InputMethodBase, virtual bool GetCompositionCharacterBounds(uint32 index, gfx::Rect* rect) OVERRIDE; virtual bool HasCompositionText() OVERRIDE; - virtual bool GetTextRange(ui::Range* range) OVERRIDE; - virtual bool GetCompositionTextRange(ui::Range* range) OVERRIDE; - virtual bool GetSelectionRange(ui::Range* range) OVERRIDE; - virtual bool SetSelectionRange(const ui::Range& range) OVERRIDE; - virtual bool DeleteRange(const ui::Range& range) OVERRIDE; + virtual bool GetTextRange(gfx::Range* range) OVERRIDE; + virtual bool GetCompositionTextRange(gfx::Range* range) OVERRIDE; + virtual bool GetSelectionRange(gfx::Range* range) OVERRIDE; + virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE; + virtual bool DeleteRange(const gfx::Range& range) OVERRIDE; virtual bool GetTextFromRange( - const ui::Range& range, string16* text) OVERRIDE; + const gfx::Range& range, string16* text) OVERRIDE; virtual void OnInputMethodChanged() OVERRIDE; virtual bool ChangeTextDirectionAndLayoutAlignment( base::i18n::TextDirection direction) OVERRIDE; @@ -90,8 +90,6 @@ class InputMethodBridge : public InputMethodBase, const bool shared_input_method_; - bool context_focused_; - DISALLOW_COPY_AND_ASSIGN(InputMethodBridge); }; diff --git a/chromium/ui/views/ime/input_method_bridge_unittest.cc b/chromium/ui/views/ime/input_method_bridge_unittest.cc index f04615291f0..64a12470731 100644 --- a/chromium/ui/views/ime/input_method_bridge_unittest.cc +++ b/chromium/ui/views/ime/input_method_bridge_unittest.cc @@ -4,7 +4,8 @@ #include "ui/aura/client/aura_constants.h" #include "ui/aura/window.h" -#include "ui/base/ime/dummy_input_method.h" +#include "ui/base/ime/dummy_input_method_delegate.h" +#include "ui/base/ime/fake_input_method.h" #include "ui/base/ime/text_input_client.h" #include "ui/views/ime/input_method.h" #include "ui/views/test/views_test_base.h" @@ -16,41 +17,10 @@ namespace views { typedef ViewsTestBase InputMethodBridgeTest; -namespace { - -class TestInputMethod : public ui::DummyInputMethod { - public: - TestInputMethod(); - virtual ~TestInputMethod(); - - virtual void SetFocusedTextInputClient(ui::TextInputClient* client) OVERRIDE; - virtual ui::TextInputClient* GetTextInputClient() const OVERRIDE; - - private: - ui::TextInputClient* text_input_client_; - - DISALLOW_COPY_AND_ASSIGN(TestInputMethod); -}; - -TestInputMethod::TestInputMethod() : text_input_client_(NULL) {} - -TestInputMethod::~TestInputMethod() {} - -void TestInputMethod::SetFocusedTextInputClient(ui::TextInputClient* client) { - // This simulates what the real InputMethod implementation does. - if (text_input_client_) - text_input_client_->GetTextInputType(); - text_input_client_ = client; -} - -ui::TextInputClient* TestInputMethod::GetTextInputClient() const { - return text_input_client_; -} - -} // namespace - TEST_F(InputMethodBridgeTest, DestructTest) { - TestInputMethod input_method; + ui::internal::DummyInputMethodDelegate input_method_delegate; + ui::FakeInputMethod input_method(&input_method_delegate); + GetContext()->SetProperty(aura::client::kRootWindowInputMethodKey, static_cast<ui::InputMethod*>(&input_method)); diff --git a/chromium/ui/views/ime/mock_input_method.cc b/chromium/ui/views/ime/mock_input_method.cc index e48af72b76c..b04dafbfa63 100644 --- a/chromium/ui/views/ime/mock_input_method.cc +++ b/chromium/ui/views/ime/mock_input_method.cc @@ -6,9 +6,9 @@ #include "base/basictypes.h" #include "base/logging.h" -#include "ui/base/events/event.h" #include "ui/base/ime/text_input_client.h" -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/views/widget/widget.h" namespace views { diff --git a/chromium/ui/views/layout/grid_layout.cc b/chromium/ui/views/layout/grid_layout.cc index 2927b88da9d..0e4d4150020 100644 --- a/chromium/ui/views/layout/grid_layout.cc +++ b/chromium/ui/views/layout/grid_layout.cc @@ -995,6 +995,9 @@ void GridLayout::AddViewState(ViewState* view_state) { void GridLayout::AddRow(Row* row) { current_row_++; remaining_row_span_--; + // GridLayout requires that if you add a View with a row span you use the same + // column set for each of the rows the view lands it. This DCHECK verifies + // that. DCHECK(remaining_row_span_ <= 0 || row->column_set() == NULL || row->column_set() == GetLastValidColumnSet()); diff --git a/chromium/ui/linux_ui/OWNERS b/chromium/ui/views/linux_ui/OWNERS index 4733a4f06bf..4733a4f06bf 100644 --- a/chromium/ui/linux_ui/OWNERS +++ b/chromium/ui/views/linux_ui/OWNERS diff --git a/chromium/ui/linux_ui/linux_ui.cc b/chromium/ui/views/linux_ui/linux_ui.cc index 40ead2fc9fa..79f0a4082c9 100644 --- a/chromium/ui/linux_ui/linux_ui.cc +++ b/chromium/ui/views/linux_ui/linux_ui.cc @@ -1,18 +1,18 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// 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 "ui/linux_ui/linux_ui.h" +#include "ui/views/linux_ui/linux_ui.h" #include "ui/shell_dialogs/linux_shell_dialog.h" namespace { -ui::LinuxUI* g_linux_ui = NULL; +views::LinuxUI* g_linux_ui = NULL; } // namespace -namespace ui { +namespace views { void LinuxUI::SetInstance(LinuxUI* instance) { delete g_linux_ui; @@ -21,8 +21,8 @@ void LinuxUI::SetInstance(LinuxUI* instance) { LinuxShellDialog::SetInstance(instance); } -const LinuxUI* LinuxUI::instance() { +LinuxUI* LinuxUI::instance() { return g_linux_ui; } -} // namespace ui +} // namespace views diff --git a/chromium/ui/linux_ui/linux_ui.gyp b/chromium/ui/views/linux_ui/linux_ui.gyp index c2140760c65..7feb238f240 100644 --- a/chromium/ui/linux_ui/linux_ui.gyp +++ b/chromium/ui/views/linux_ui/linux_ui.gyp @@ -1,4 +1,4 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. +# 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. diff --git a/chromium/ui/linux_ui/linux_ui.h b/chromium/ui/views/linux_ui/linux_ui.h index f609e9a78a0..443677c812b 100644 --- a/chromium/ui/linux_ui/linux_ui.h +++ b/chromium/ui/views/linux_ui/linux_ui.h @@ -1,14 +1,14 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// 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. -#ifndef UI_LINUX_UI_LINUX_UI_H_ -#define UI_LINUX_UI_LINUX_UI_H_ +#ifndef UI_VIEWS_LINUX_UI_LINUX_UI_H_ +#define UI_VIEWS_LINUX_UI_LINUX_UI_H_ #include "third_party/skia/include/core/SkColor.h" -#include "ui/linux_ui/linux_ui_export.h" -#include "ui/linux_ui/status_icon_linux.h" #include "ui/shell_dialogs/linux_shell_dialog.h" +#include "ui/views/linux_ui/status_icon_linux.h" +#include "ui/views/views_export.h" // The main entrypoint into Linux toolkit specific code. GTK code should only // be executed behind this interface. @@ -19,6 +19,10 @@ class Image; namespace ui { class NativeTheme; +} + +namespace views { +class WindowButtonOrderObserver; // Adapter class with targets to render like different toolkits. Set by any // project that wants to do linux desktop native rendering. @@ -27,10 +31,7 @@ class NativeTheme; // minimum) GTK2 and GTK3. LinuxUI::instance() should actually be a very // complex method that pokes around with dlopen against a libuigtk2.so, a // liuigtk3.so, etc. -// -// TODO(erg): This class should be folded into ui/views/ instead of living in -// its own component once we've deleted out the GTK+ port. -class LINUX_UI_EXPORT LinuxUI : public LinuxShellDialog { +class VIEWS_EXPORT LinuxUI : public ui::LinuxShellDialog { public: virtual ~LinuxUI() {} @@ -42,7 +43,7 @@ class LINUX_UI_EXPORT LinuxUI : public LinuxShellDialog { // // Can return NULL, in case no toolkit has been set. (For example, if we're // running with the "--ash" flag.) - static const LinuxUI* instance(); + static LinuxUI* instance(); // Returns an themed image per theme_provider.h virtual bool UseNativeTheme() const = 0; @@ -52,7 +53,7 @@ class LINUX_UI_EXPORT LinuxUI : public LinuxShellDialog { // Returns a NativeTheme that will provide system colors and draw system // style widgets. - virtual NativeTheme* GetNativeTheme() const = 0; + virtual ui::NativeTheme* GetNativeTheme() const = 0; // Returns whether we should be using the native theme provided by this // object by default. @@ -70,8 +71,18 @@ class LINUX_UI_EXPORT LinuxUI : public LinuxShellDialog { virtual scoped_ptr<StatusIconLinux> CreateLinuxStatusIcon( const gfx::ImageSkia& image, const string16& tool_tip) const = 0; + + // Notifies the observer about changes about how window buttons should be + // laid out. If the order is anything other than the default min,max,close on + // the right, will immediately send a button change event to the observer. + virtual void AddWindowButtonOrderObserver( + WindowButtonOrderObserver* observer) = 0; + + // Removes the observer from the LinuxUI's list. + virtual void RemoveWindowButtonOrderObserver( + WindowButtonOrderObserver* observer) = 0; }; -} // namespace ui +} // namespace views -#endif // UI_LINUX_UI_LINUX_UI_H_ +#endif // UI_VIEWS_LINUX_UI_LINUX_UI_H_ diff --git a/chromium/ui/linux_ui/status_icon_linux.cc b/chromium/ui/views/linux_ui/status_icon_linux.cc index 1e273d3589f..bf2ec05a9f1 100644 --- a/chromium/ui/linux_ui/status_icon_linux.cc +++ b/chromium/ui/views/linux_ui/status_icon_linux.cc @@ -2,7 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/linux_ui/status_icon_linux.h" +#include "ui/views/linux_ui/status_icon_linux.h" + +namespace views { StatusIconLinux::Delegate::~Delegate() { } @@ -12,3 +14,8 @@ StatusIconLinux::StatusIconLinux() : delegate_(NULL) { StatusIconLinux::~StatusIconLinux() { } + +void StatusIconLinux::RefreshPlatformContextMenu() { +} + +} // namespace views diff --git a/chromium/ui/linux_ui/status_icon_linux.h b/chromium/ui/views/linux_ui/status_icon_linux.h index fbbf28f304e..5ed8be21a7e 100644 --- a/chromium/ui/linux_ui/status_icon_linux.h +++ b/chromium/ui/views/linux_ui/status_icon_linux.h @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_LINUX_UI_STATUS_ICON_LINUX_H_ -#define UI_LINUX_UI_STATUS_ICON_LINUX_H_ +#ifndef UI_VIEWS_LINUX_UI_STATUS_ICON_LINUX_H_ +#define UI_VIEWS_LINUX_UI_STATUS_ICON_LINUX_H_ #include "base/strings/string16.h" -#include "ui/linux_ui/linux_ui_export.h" +#include "ui/views/views_export.h" namespace gfx { class ImageSkia; @@ -16,11 +16,13 @@ namespace ui { class MenuModel; } // namespace ui +namespace views { + // Since liblinux_ui cannot have dependencies on any chrome browser components // we cannot inherit from StatusIcon. So we implement the necessary methods // and let a wrapper class implement the StatusIcon interface and defer the -// callbacks to a delegate. -class LINUX_UI_EXPORT StatusIconLinux { +// callbacks to a delegate. For the same reason, do not use StatusIconMenuModel. +class VIEWS_EXPORT StatusIconLinux { public: class Delegate { public: @@ -43,6 +45,11 @@ class LINUX_UI_EXPORT StatusIconLinux { // subclass should destroy the existing native context menu on this call. virtual void UpdatePlatformContextMenu(ui::MenuModel* model) = 0; + // Update all the enabled/checked states and the dynamic labels. Some status + // icon implementations do not refresh the native menu before showing so we + // need to manually refresh it when the menu model changes. + virtual void RefreshPlatformContextMenu(); + Delegate* delegate() { return delegate_; } void set_delegate(Delegate* delegate) { delegate_ = delegate; } @@ -50,4 +57,6 @@ class LINUX_UI_EXPORT StatusIconLinux { Delegate* delegate_; }; +} // namespace views + #endif // UI_LINUX_UI_STATUS_ICON_LINUX_H_ diff --git a/chromium/ui/views/linux_ui/window_button_order_observer.h b/chromium/ui/views/linux_ui/window_button_order_observer.h new file mode 100644 index 00000000000..96b7cb8290f --- /dev/null +++ b/chromium/ui/views/linux_ui/window_button_order_observer.h @@ -0,0 +1,29 @@ +// Copyright (c) 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. + +#ifndef UI_VIEWS_LINUX_UI_WINDOW_BUTTON_ORDER_OBSERVER_H_ +#define UI_VIEWS_LINUX_UI_WINDOW_BUTTON_ORDER_OBSERVER_H_ + +#include <vector> + +#include "ui/views/window/frame_buttons.h" + +namespace views { + +// Observer interface to receive the ordering of the min,max,close buttons. +class WindowButtonOrderObserver { + public: + // Called when first added to the LinuxUI class, or on a system-wide + // configuration event. + virtual void OnWindowButtonOrderingChange( + const std::vector<views::FrameButton>& leading_buttons, + const std::vector<views::FrameButton>& trailing_buttons) = 0; + + protected: + virtual ~WindowButtonOrderObserver() {} +}; + +} // namespace views + +#endif // UI_VIEWS_LINUX_UI_WINDOW_BUTTON_ORDER_OBSERVER_H_ diff --git a/chromium/ui/views/mouse_constants.cc b/chromium/ui/views/mouse_constants.cc new file mode 100644 index 00000000000..b2f3b964af3 --- /dev/null +++ b/chromium/ui/views/mouse_constants.cc @@ -0,0 +1,12 @@ +// 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 "ui/views/mouse_constants.h" + +namespace views { + +const int kMinimumMsPressedToActivate = 200; +const int kMinimumMsBetweenButtonClicks = 100; + +} // namespace views diff --git a/chromium/ui/views/mouse_constants.h b/chromium/ui/views/mouse_constants.h new file mode 100644 index 00000000000..e22c75cdd65 --- /dev/null +++ b/chromium/ui/views/mouse_constants.h @@ -0,0 +1,25 @@ +// 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. + +#ifndef UI_VIEWS_MOUSE_CONSTANTS_H_ +#define UI_VIEWS_MOUSE_CONSTANTS_H_ + +#include "base/basictypes.h" +#include "ui/views/views_export.h" + +namespace views { + +// The amount of time the mouse should be down before a mouse release is +// considered intentional. This is to prevent spurious mouse releases from +// activating controls, especially when some UI element is revealed under the +// source of the activation (ex. menus showing underneath menu buttons). +VIEWS_EXPORT extern const int kMinimumMsPressedToActivate; + +// The amount of time, in milliseconds, between clicks until they're considered +// intentionally different. +VIEWS_EXPORT extern const int kMinimumMsBetweenButtonClicks; + +} // namespace views + +#endif // UI_VIEWS_MOUSE_CONSTANTS_H_ diff --git a/chromium/ui/views/mouse_watcher.cc b/chromium/ui/views/mouse_watcher.cc index e4f156f0ea5..5a2b4bd0ae8 100644 --- a/chromium/ui/views/mouse_watcher.cc +++ b/chromium/ui/views/mouse_watcher.cc @@ -9,8 +9,8 @@ #include "base/event_types.h" #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop.h" -#include "ui/base/events/event_constants.h" -#include "ui/base/events/event_utils.h" +#include "ui/events/event_constants.h" +#include "ui/events/event_utils.h" #include "ui/gfx/screen.h" namespace views { diff --git a/chromium/ui/views/mouse_watcher_view_host.cc b/chromium/ui/views/mouse_watcher_view_host.cc index 1d420fa1cbc..54412cf10d5 100644 --- a/chromium/ui/views/mouse_watcher_view_host.cc +++ b/chromium/ui/views/mouse_watcher_view_host.cc @@ -50,7 +50,7 @@ bool MouseWatcherViewHost::IsMouseOverWindow() { return false; return gfx::Screen::GetScreenFor(widget->GetNativeView())-> - GetWindowAtCursorScreenPoint() == widget->GetNativeWindow(); + GetWindowUnderCursor() == widget->GetNativeWindow(); } } // namespace views diff --git a/chromium/ui/views/native_theme_delegate.h b/chromium/ui/views/native_theme_delegate.h index d4bc880fd8d..f17f164462e 100644 --- a/chromium/ui/views/native_theme_delegate.h +++ b/chromium/ui/views/native_theme_delegate.h @@ -34,7 +34,7 @@ class VIEWS_EXPORT NativeThemeDelegate { // If the native theme drawign should be animated, return the Animation object // that controlls it. If no animation is ongoing, NULL may be returned. - virtual const ui::Animation* GetThemeAnimation() const = 0; + virtual const gfx::Animation* GetThemeAnimation() const = 0; // If animation is onging, this returns the background native theme state. virtual ui::NativeTheme::State GetBackgroundThemeState( diff --git a/chromium/ui/views/run_all_unittests.cc b/chromium/ui/views/run_all_unittests.cc index 6c425d7a31e..fb99c447d71 100644 --- a/chromium/ui/views/run_all_unittests.cc +++ b/chromium/ui/views/run_all_unittests.cc @@ -3,8 +3,10 @@ // found in the LICENSE file. #include "base/basictypes.h" +#include "base/bind.h" #include "base/compiler_specific.h" #include "base/test/test_suite.h" +#include "base/test/unit_test_launcher.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_base_paths.h" #include "ui/views/view.h" @@ -25,5 +27,9 @@ class ViewTestSuite : public base::TestSuite { }; int main(int argc, char** argv) { - return ViewTestSuite(argc, argv).Run(); + ViewTestSuite test_suite(argc, argv); + + return base::LaunchUnitTests( + argc, argv, base::Bind(&ViewTestSuite::Run, + base::Unretained(&test_suite))); } diff --git a/chromium/ui/views/touchui/touch_selection_controller_impl.cc b/chromium/ui/views/touchui/touch_selection_controller_impl.cc index 8b6b35116c8..89f6bdcafa8 100644 --- a/chromium/ui/views/touchui/touch_selection_controller_impl.cc +++ b/chromium/ui/views/touchui/touch_selection_controller_impl.cc @@ -193,7 +193,7 @@ class TouchSelectionControllerImpl::EditingHandleView case ui::ET_GESTURE_SCROLL_BEGIN: widget_->SetCapture(this); controller_->SetDraggingHandle(this); - drag_offset_ = event->y() - cursor_height() - + drag_offset_ = event->y() - cursor_height() + kSelectionHandleVerticalDragOffset; break; case ui::ET_GESTURE_SCROLL_UPDATE: { @@ -259,6 +259,10 @@ class TouchSelectionControllerImpl::EditingHandleView scoped_ptr<Widget> widget_; TouchSelectionControllerImpl* controller_; gfx::Rect selection_rect_; + + // Vertical offset between the scroll event position and the drag position + // reported to the client view (see the ASCII figure at the top of the file + // and its description for more details). int drag_offset_; // If set to true, the handle will not draw anything, hence providing an empty diff --git a/chromium/ui/views/touchui/touch_selection_controller_impl_unittest.cc b/chromium/ui/views/touchui/touch_selection_controller_impl_unittest.cc index 2925046fb6a..54c997223c2 100644 --- a/chromium/ui/views/touchui/touch_selection_controller_impl_unittest.cc +++ b/chromium/ui/views/touchui/touch_selection_controller_impl_unittest.cc @@ -200,7 +200,7 @@ TEST_F(TouchSelectionControllerImplTest, SelectionInTextfieldTest) { textfield_view_->OnGestureEvent(&tap); // Test selecting a range. - textfield_->SelectRange(ui::Range(3, 7)); + textfield_->SelectRange(gfx::Range(3, 7)); VERIFY_HANDLE_POSITIONS(false); // Test selecting everything. @@ -237,35 +237,35 @@ TEST_F(TouchSelectionControllerImplTest, SelectionInBidiTextfieldTest) { VERIFY_HANDLE_POSITIONS(false); // Test selection range inside one run and starts or ends at run boundary. - textfield_->SelectRange(ui::Range(2, 3)); + textfield_->SelectRange(gfx::Range(2, 3)); VERIFY_HANDLE_POSITIONS(false); - textfield_->SelectRange(ui::Range(3, 2)); + textfield_->SelectRange(gfx::Range(3, 2)); VERIFY_HANDLE_POSITIONS(false); - textfield_->SelectRange(ui::Range(3, 4)); + textfield_->SelectRange(gfx::Range(3, 4)); VERIFY_HANDLE_POSITIONS(false); - textfield_->SelectRange(ui::Range(4, 3)); + textfield_->SelectRange(gfx::Range(4, 3)); VERIFY_HANDLE_POSITIONS(false); - textfield_->SelectRange(ui::Range(3, 6)); + textfield_->SelectRange(gfx::Range(3, 6)); VERIFY_HANDLE_POSITIONS(false); - textfield_->SelectRange(ui::Range(6, 3)); + textfield_->SelectRange(gfx::Range(6, 3)); VERIFY_HANDLE_POSITIONS(false); // Test selection range accross runs. - textfield_->SelectRange(ui::Range(0, 6)); + textfield_->SelectRange(gfx::Range(0, 6)); VERIFY_HANDLE_POSITIONS(false); - textfield_->SelectRange(ui::Range(6, 0)); + textfield_->SelectRange(gfx::Range(6, 0)); VERIFY_HANDLE_POSITIONS(false); - textfield_->SelectRange(ui::Range(1, 4)); + textfield_->SelectRange(gfx::Range(1, 4)); VERIFY_HANDLE_POSITIONS(false); - textfield_->SelectRange(ui::Range(4, 1)); + textfield_->SelectRange(gfx::Range(4, 1)); VERIFY_HANDLE_POSITIONS(false); } @@ -278,7 +278,7 @@ TEST_F(TouchSelectionControllerImplTest, SelectRectCallbackTest) { ui::GestureEvent tap(ui::ET_GESTURE_TAP, 0, 0, 0, base::TimeDelta(), ui::GestureEventDetails(ui::ET_GESTURE_TAP, 1.0f, 0.0f), 0); textfield_view_->OnGestureEvent(&tap); - textfield_->SelectRange(ui::Range(3, 7)); + textfield_->SelectRange(gfx::Range(3, 7)); EXPECT_EQ(UTF16ToUTF8(textfield_->GetSelectedText()), "tfie"); VERIFY_HANDLE_POSITIONS(false); @@ -318,7 +318,7 @@ TEST_F(TouchSelectionControllerImplTest, SelectRectInBidiCallbackTest) { textfield_view_->OnGestureEvent(&tap); // Select [c] from left to right. - textfield_->SelectRange(ui::Range(2, 3)); + textfield_->SelectRange(gfx::Range(2, 3)); EXPECT_EQ(WideToUTF16(L"c"), textfield_->GetSelectedText()); VERIFY_HANDLE_POSITIONS(false); @@ -336,7 +336,7 @@ TEST_F(TouchSelectionControllerImplTest, SelectRectInBidiCallbackTest) { VERIFY_HANDLE_POSITIONS(true); // Select [c] from right to left. - textfield_->SelectRange(ui::Range(3, 2)); + textfield_->SelectRange(gfx::Range(3, 2)); EXPECT_EQ(WideToUTF16(L"c"), textfield_->GetSelectedText()); VERIFY_HANDLE_POSITIONS(false); @@ -353,7 +353,7 @@ TEST_F(TouchSelectionControllerImplTest, SelectRectInBidiCallbackTest) { VERIFY_HANDLE_POSITIONS(false); // Select [\x5e1] from right to left. - textfield_->SelectRange(ui::Range(3, 4)); + textfield_->SelectRange(gfx::Range(3, 4)); EXPECT_EQ(WideToUTF16(L"\x05e1"), textfield_->GetSelectedText()); VERIFY_HANDLE_POSITIONS(false); @@ -379,7 +379,7 @@ TEST_F(TouchSelectionControllerImplTest, SelectRectInBidiCallbackTest) { VERIFY_HANDLE_POSITIONS(true); // Select [\x5e1] from left to right. - textfield_->SelectRange(ui::Range(4, 3)); + textfield_->SelectRange(gfx::Range(4, 3)); EXPECT_EQ(WideToUTF16(L"\x05e1"), textfield_->GetSelectedText()); VERIFY_HANDLE_POSITIONS(false); @@ -398,7 +398,7 @@ TEST_F(TouchSelectionControllerImplTest, SelectRectInBidiCallbackTest) { VERIFY_HANDLE_POSITIONS(false); // Select [\x05r3] from right to left. - textfield_->SelectRange(ui::Range(5, 6)); + textfield_->SelectRange(gfx::Range(5, 6)); EXPECT_EQ(WideToUTF16(L"\x05e3"), textfield_->GetSelectedText()); VERIFY_HANDLE_POSITIONS(false); @@ -415,7 +415,7 @@ TEST_F(TouchSelectionControllerImplTest, SelectRectInBidiCallbackTest) { VERIFY_HANDLE_POSITIONS(true); // Select [\x05r3] from left to right. - textfield_->SelectRange(ui::Range(6, 5)); + textfield_->SelectRange(gfx::Range(6, 5)); EXPECT_EQ(WideToUTF16(L"\x05e3"), textfield_->GetSelectedText()); VERIFY_HANDLE_POSITIONS(false); @@ -447,12 +447,12 @@ TEST_F(TouchSelectionControllerImplTest, textfield_view_->OnGestureEvent(&tap); // Select some text such that one handle is hidden. - textfield_->SelectRange(ui::Range(10, textfield_text.length())); + textfield_->SelectRange(gfx::Range(10, textfield_text.length())); // Check that one selection handle is hidden. EXPECT_FALSE(IsSelectionHandle1Visible()); EXPECT_TRUE(IsSelectionHandle2Visible()); - EXPECT_EQ(ui::Range(10, textfield_text.length()), + EXPECT_EQ(gfx::Range(10, textfield_text.length()), textfield_->GetSelectedRange()); // Drag the visible handle around and make sure the selection end point of the diff --git a/chromium/ui/views/view.cc b/chromium/ui/views/view.cc index 080df12881d..d816a0a16d0 100644 --- a/chromium/ui/views/view.cc +++ b/chromium/ui/views/view.cc @@ -43,6 +43,10 @@ #include "ui/views/widget/tooltip_manager.h" #include "ui/views/widget/widget.h" +#if defined(USE_AURA) +#include "ui/base/cursor/cursor.h" +#endif + #if defined(OS_WIN) #include "base/win/scoped_gdi_object.h" #endif @@ -176,7 +180,6 @@ View::View() focus_border_(FocusBorder::CreateDashedFocusBorder()), flip_canvas_on_paint_for_rtl_ui_(false), paint_to_layer_(false), - accelerator_registration_delayed_(false), accelerator_focus_manager_(NULL), registered_accelerator_count_(0), next_focusable_view_(NULL), @@ -1299,21 +1302,13 @@ void View::ViewHierarchyChanged(const ViewHierarchyChangedDetails& details) { void View::VisibilityChanged(View* starting_from, bool is_visible) { } -void View::NativeViewHierarchyChanged(bool attached, - gfx::NativeView native_view, - internal::RootView* root_view) { +void View::NativeViewHierarchyChanged() { FocusManager* focus_manager = GetFocusManager(); - if (!accelerator_registration_delayed_ && - accelerator_focus_manager_ && - accelerator_focus_manager_ != focus_manager) { + if (accelerator_focus_manager_ != focus_manager) { UnregisterAccelerators(true); - accelerator_registration_delayed_ = true; - } - if (accelerator_registration_delayed_ && attached) { - if (focus_manager) { + + if (focus_manager) RegisterPendingAccelerators(); - accelerator_registration_delayed_ = false; - } } } @@ -1815,14 +1810,10 @@ void View::PropagateAddNotifications( ViewHierarchyChangedImpl(true, details); } -void View::PropagateNativeViewHierarchyChanged(bool attached, - gfx::NativeView native_view, - internal::RootView* root_view) { +void View::PropagateNativeViewHierarchyChanged() { for (int i = 0, count = child_count(); i < count; ++i) - child_at(i)->PropagateNativeViewHierarchyChanged(attached, - native_view, - root_view); - NativeViewHierarchyChanged(attached, native_view, root_view); + child_at(i)->PropagateNativeViewHierarchyChanged(); + NativeViewHierarchyChanged(); } void View::ViewHierarchyChangedImpl( @@ -1832,13 +1823,8 @@ void View::ViewHierarchyChangedImpl( if (details.is_add) { // If you get this registration, you are part of a subtree that has been // added to the view hierarchy. - if (GetFocusManager()) { + if (GetFocusManager()) RegisterPendingAccelerators(); - } else { - // Delay accelerator registration until visible as we do not have - // focus manager until then. - accelerator_registration_delayed_ = true; - } } else { if (details.child == this) UnregisterAccelerators(true); @@ -1851,7 +1837,7 @@ void View::ViewHierarchyChangedImpl( if (widget) widget->UpdateRootLayers(); } else if (!details.is_add && details.child == this) { - // Make sure the layers beloning to the subtree rooted at |child| get + // Make sure the layers belonging to the subtree rooted at |child| get // removed from layers that do not belong in the same subtree. OrphanLayers(); if (use_acceleration_when_possible) { @@ -2017,7 +2003,7 @@ bool View::ConvertPointForAncestor(const View* ancestor, // TODO(sad): Have some way of caching the transformation results. bool result = GetTransformRelativeTo(ancestor, &trans); gfx::Point3F p(*point); - trans.TransformPoint(p); + trans.TransformPoint(&p); *point = gfx::ToFlooredPoint(p.AsPointF()); return result; } @@ -2027,7 +2013,7 @@ bool View::ConvertPointFromAncestor(const View* ancestor, gfx::Transform trans; bool result = GetTransformRelativeTo(ancestor, &trans); gfx::Point3F p(*point); - trans.TransformPointReverse(p); + trans.TransformPointReverse(&p); *point = gfx::ToFlooredPoint(p.AsPointF()); return result; } @@ -2229,9 +2215,6 @@ void View::UnregisterAccelerators(bool leave_data_intact) { if (GetWidget()) { if (accelerator_focus_manager_) { - // We may not have a FocusManager if the window containing us is being - // closed, in which case the FocusManager is being deleted so there is - // nothing to unregister. accelerator_focus_manager_->UnregisterAccelerators(this); accelerator_focus_manager_ = NULL; } @@ -2317,11 +2300,20 @@ void View::UpdateTooltip() { bool View::DoDrag(const ui::LocatedEvent& event, const gfx::Point& press_pt, ui::DragDropTypes::DragEventSource source) { -#if !defined(OS_MACOSX) int drag_operations = GetDragOperations(press_pt); if (drag_operations == ui::DragDropTypes::DRAG_NONE) return false; + Widget* widget = GetWidget(); + // We should only start a drag from an event, implying we have a widget. + DCHECK(widget); + + // Don't attempt to start a drag while in the process of dragging. This is + // especially important on X where we can get multiple mouse move events when + // we start the drag. + if (widget->dragged_view()) + return false; + OSExchangeData data; WriteDragData(press_pt, &data); @@ -2329,12 +2321,9 @@ bool View::DoDrag(const ui::LocatedEvent& event, // the RootView can detect it and avoid calling us back. gfx::Point widget_location(event.location()); ConvertPointToWidget(this, &widget_location); - GetWidget()->RunShellDrag(this, data, widget_location, drag_operations, - source); + widget->RunShellDrag(this, data, widget_location, drag_operations, source); + // WARNING: we may have been deleted. return true; -#else - return false; -#endif // !defined(OS_MACOSX) } } // namespace views diff --git a/chromium/ui/views/view.h b/chromium/ui/views/view.h index 2ffc6204be7..b0ed0c0a314 100644 --- a/chromium/ui/views/view.h +++ b/chromium/ui/views/view.h @@ -20,11 +20,11 @@ #include "ui/base/accessibility/accessibility_types.h" #include "ui/base/dragdrop/drag_drop_types.h" #include "ui/base/dragdrop/os_exchange_data.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_target.h" #include "ui/base/ui_base_types.h" #include "ui/compositor/layer_delegate.h" #include "ui/compositor/layer_owner.h" +#include "ui/events/event.h" +#include "ui/events/event_target.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/rect.h" #include "ui/gfx/vector2d.h" @@ -1032,17 +1032,13 @@ class VIEWS_EXPORT View : public ui::LayerDelegate, // invoked for that view as well as all the children recursively. virtual void VisibilityChanged(View* starting_from, bool is_visible); - // Called when the native view hierarchy changed. - // |attached| is true if that view has been attached to a new NativeView - // hierarchy, false if it has been detached. - // |native_view| is the NativeView this view was attached/detached from, and - // |root_view| is the root view associated with the NativeView. - // Views created without a native view parent don't have a focus manager. - // When this function is called they could do the processing that requires - // it - like registering accelerators, for example. - virtual void NativeViewHierarchyChanged(bool attached, - gfx::NativeView native_view, - internal::RootView* root_view); + // This method is invoked when the parent NativeView of the widget that the + // view is attached to has changed and the view hierarchy has not changed. + // ViewHierarchyChanged() is called when the parent NativeView of the widget + // that the view is attached to is changed as a result of changing the view + // hierarchy. Overriding this method is useful for tracking which + // FocusManager manages this view. + virtual void NativeViewHierarchyChanged(); // Painting ------------------------------------------------------------------ @@ -1260,9 +1256,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate, // Propagates NativeViewHierarchyChanged() notification through all the // children. - void PropagateNativeViewHierarchyChanged(bool attached, - gfx::NativeView native_view, - internal::RootView* root_view); + void PropagateNativeViewHierarchyChanged(); // Takes care of registering/unregistering accelerators if // |register_accelerators| true and calls ViewHierarchyChanged(). @@ -1503,10 +1497,6 @@ class VIEWS_EXPORT View : public ui::LayerDelegate, // Accelerators -------------------------------------------------------------- - // true if when we were added to hierarchy we were without focus manager - // attempt addition when ancestor chain changed. - bool accelerator_registration_delayed_; - // Focus manager accelerators registered on. FocusManager* accelerator_focus_manager_; diff --git a/chromium/ui/views/view_unittest.cc b/chromium/ui/views/view_unittest.cc index 53b28f3cb93..e0fa07e46b1 100644 --- a/chromium/ui/views/view_unittest.cc +++ b/chromium/ui/views/view_unittest.cc @@ -12,12 +12,12 @@ #include "testing/gmock/include/gmock/gmock.h" #include "ui/base/accelerators/accelerator.h" #include "ui/base/clipboard/clipboard.h" -#include "ui/base/events/event.h" -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/base/l10n/l10n_util.h" #include "ui/compositor/compositor.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animator.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/canvas.h" #include "ui/gfx/path.h" #include "ui/gfx/transform.h" @@ -1545,131 +1545,71 @@ TEST_F(ViewTest, DISABLED_RerouteMouseWheelTest) { //////////////////////////////////////////////////////////////////////////////// // Native view hierachy //////////////////////////////////////////////////////////////////////////////// -class TestNativeViewHierarchy : public View { +class ToplevelWidgetObserverView : public View { public: - TestNativeViewHierarchy() { + ToplevelWidgetObserverView() : toplevel_(NULL) { } - - virtual void NativeViewHierarchyChanged( - bool attached, - gfx::NativeView native_view, - internal::RootView* root_view) OVERRIDE { - NotificationInfo info; - info.attached = attached; - info.native_view = native_view; - info.root_view = root_view; - notifications_.push_back(info); - }; - struct NotificationInfo { - bool attached; - gfx::NativeView native_view; - internal::RootView* root_view; - }; - static const size_t kTotalViews = 2; - std::vector<NotificationInfo> notifications_; -}; - -class TestChangeNativeViewHierarchy { - public: - explicit TestChangeNativeViewHierarchy(ViewTest *view_test) { - view_test_ = view_test; - native_host_ = new NativeViewHost(); - host_ = new Widget; - Widget::InitParams params = - view_test->CreateParams(Widget::InitParams::TYPE_POPUP); - params.bounds = gfx::Rect(0, 0, 500, 300); - host_->Init(params); - host_->GetRootView()->AddChildView(native_host_); - for (size_t i = 0; i < TestNativeViewHierarchy::kTotalViews; ++i) { - windows_[i] = new Widget; - Widget::InitParams params(Widget::InitParams::TYPE_CONTROL); - params.parent = host_->GetNativeView(); - params.bounds = gfx::Rect(0, 0, 500, 300); - windows_[i]->Init(params); - root_views_[i] = windows_[i]->GetRootView(); - test_views_[i] = new TestNativeViewHierarchy; - root_views_[i]->AddChildView(test_views_[i]); - } + virtual ~ToplevelWidgetObserverView() { } - ~TestChangeNativeViewHierarchy() { - for (size_t i = 0; i < TestNativeViewHierarchy::kTotalViews; ++i) { - windows_[i]->Close(); + // View overrides: + virtual void ViewHierarchyChanged( + const ViewHierarchyChangedDetails& details) OVERRIDE { + if (details.is_add) { + toplevel_ = GetWidget() ? GetWidget()->GetTopLevelWidget() : NULL; + } else { + toplevel_ = NULL; } - host_->Close(); - // Will close and self-delete widgets - no need to manually delete them. - view_test_->RunPendingMessages(); } - - void CheckEnumeratingNativeWidgets() { - if (!host_->GetTopLevelWidget()) - return; - Widget::Widgets widgets; - Widget::GetAllChildWidgets(host_->GetNativeView(), &widgets); - EXPECT_EQ(TestNativeViewHierarchy::kTotalViews + 1, widgets.size()); - // Unfortunately there is no guarantee the sequence of views here so always - // go through all of them. - for (Widget::Widgets::iterator i = widgets.begin(); - i != widgets.end(); ++i) { - View* root_view = (*i)->GetRootView(); - if (host_->GetRootView() == root_view) - continue; - size_t j; - for (j = 0; j < TestNativeViewHierarchy::kTotalViews; ++j) - if (root_views_[j] == root_view) - break; - // EXPECT_LT/GT/GE() fails to compile with class-defined constants - // with gcc, with error - // "error: undefined reference to 'TestNativeViewHierarchy::kTotalViews'" - // so I forced to use EXPECT_TRUE() instead. - EXPECT_TRUE(TestNativeViewHierarchy::kTotalViews > j); - } + virtual void NativeViewHierarchyChanged() OVERRIDE { + toplevel_ = GetWidget() ? GetWidget()->GetTopLevelWidget() : NULL; } - void CheckChangingHierarhy() { - size_t i; - for (i = 0; i < TestNativeViewHierarchy::kTotalViews; ++i) { - // TODO(georgey): use actual hierarchy changes to send notifications. - static_cast<internal::RootView*>(root_views_[i])-> - NotifyNativeViewHierarchyChanged(false, host_->GetNativeView()); - static_cast<internal::RootView*>(root_views_[i])-> - NotifyNativeViewHierarchyChanged(true, host_->GetNativeView()); - } - for (i = 0; i < TestNativeViewHierarchy::kTotalViews; ++i) { - ASSERT_EQ(static_cast<size_t>(2), test_views_[i]->notifications_.size()); - EXPECT_FALSE(test_views_[i]->notifications_[0].attached); - EXPECT_EQ(host_->GetNativeView(), - test_views_[i]->notifications_[0].native_view); - EXPECT_EQ(root_views_[i], test_views_[i]->notifications_[0].root_view); - EXPECT_TRUE(test_views_[i]->notifications_[1].attached); - EXPECT_EQ(host_->GetNativeView(), - test_views_[i]->notifications_[1].native_view); - EXPECT_EQ(root_views_[i], test_views_[i]->notifications_[1].root_view); - } - } + Widget* toplevel() { return toplevel_; } - NativeViewHost* native_host_; - Widget* host_; - Widget* windows_[TestNativeViewHierarchy::kTotalViews]; - View* root_views_[TestNativeViewHierarchy::kTotalViews]; - TestNativeViewHierarchy* test_views_[TestNativeViewHierarchy::kTotalViews]; - ViewTest* view_test_; -}; + private: + Widget* toplevel_; -TEST_F(ViewTest, ChangeNativeViewHierarchyFindRoots) { - // TODO(georgey): Fix the test for Linux -#if defined(OS_WIN) - TestChangeNativeViewHierarchy test(this); - test.CheckEnumeratingNativeWidgets(); -#endif -} + DISALLOW_COPY_AND_ASSIGN(ToplevelWidgetObserverView); +}; -TEST_F(ViewTest, ChangeNativeViewHierarchyChangeHierarchy) { - // TODO(georgey): Fix the test for Linux -#if defined(OS_WIN) - TestChangeNativeViewHierarchy test(this); - test.CheckChangingHierarhy(); -#endif +// Test that a view can track the current top level widget by overriding +// View::ViewHierarchyChanged() and View::NativeViewHierarchyChanged(). +TEST_F(ViewTest, NativeViewHierarchyChanged) { + scoped_ptr<Widget> toplevel1(new Widget); + Widget::InitParams toplevel1_params = + CreateParams(Widget::InitParams::TYPE_POPUP); + toplevel1_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + toplevel1->Init(toplevel1_params); + + scoped_ptr<Widget> toplevel2(new Widget); + Widget::InitParams toplevel2_params = + CreateParams(Widget::InitParams::TYPE_POPUP); + toplevel2_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + toplevel2->Init(toplevel2_params); + + Widget* child = new Widget; + Widget::InitParams child_params(Widget::InitParams::TYPE_CONTROL); + child_params.parent = toplevel1->GetNativeView(); + child->Init(child_params); + + ToplevelWidgetObserverView* observer_view = + new ToplevelWidgetObserverView(); + EXPECT_EQ(NULL, observer_view->toplevel()); + + child->SetContentsView(observer_view); + EXPECT_EQ(toplevel1, observer_view->toplevel()); + + Widget::ReparentNativeView(child->GetNativeView(), + toplevel2->GetNativeView()); + EXPECT_EQ(toplevel2, observer_view->toplevel()); + + observer_view->parent()->RemoveChildView(observer_view); + EXPECT_EQ(NULL, observer_view->toplevel()); + + // Make |observer_view| |child|'s contents view again so that it gets deleted + // with the widget. + child->SetContentsView(observer_view); } //////////////////////////////////////////////////////////////////////////////// diff --git a/chromium/ui/views/views.gyp b/chromium/ui/views/views.gyp index de8cdef4e19..8ba7958a728 100644 --- a/chromium/ui/views/views.gyp +++ b/chromium/ui/views/views.gyp @@ -95,11 +95,6 @@ 'controls/combobox/combobox.cc', 'controls/combobox/combobox.h', 'controls/combobox/combobox_listener.h', - 'controls/combobox/native_combobox_views.cc', - 'controls/combobox/native_combobox_views.h', - 'controls/combobox/native_combobox_win.cc', - 'controls/combobox/native_combobox_win.h', - 'controls/combobox/native_combobox_wrapper.h', 'controls/focusable_border.cc', 'controls/focusable_border.h', 'controls/glow_hover_controller.cc', @@ -237,6 +232,8 @@ 'controls/tree/tree_view_controller.h', 'corewm/base_focus_rules.cc', 'corewm/base_focus_rules.h', + 'corewm/capture_controller.cc', + 'corewm/capture_controller.h', 'corewm/compound_event_filter.cc', 'corewm/compound_event_filter.h', 'corewm/corewm_switches.cc', @@ -273,6 +270,9 @@ 'drag_controller.h', 'drag_utils.cc', 'drag_utils.h', + 'event_utils.h', + 'event_utils_aura.cc', + 'event_utils_win.cc', 'focus/accelerator_handler.h', 'focus/accelerator_handler_aura.cc', 'focus/accelerator_handler_win.cc', @@ -308,10 +308,17 @@ 'layout/layout_constants.h', 'layout/layout_manager.cc', 'layout/layout_manager.h', + 'linux_ui/linux_ui.h', + 'linux_ui/linux_ui.cc', + 'linux_ui/status_icon_linux.h', + 'linux_ui/status_icon_linux.cc', + 'linux_ui/window_button_order_observer.h', 'metrics.cc', 'metrics.h', 'metrics_aura.cc', 'metrics_win.cc', + 'mouse_constants.cc', + 'mouse_constants.h', 'mouse_watcher.cc', 'mouse_watcher.h', 'mouse_watcher_view_host.cc', @@ -347,10 +354,6 @@ 'widget/aero_tooltip_manager.h', 'widget/child_window_message_processor.cc', 'widget/child_window_message_processor.h', - 'widget/desktop_aura/desktop_activation_client.cc', - 'widget/desktop_aura/desktop_activation_client.h', - 'widget/desktop_aura/desktop_capture_client.cc', - 'widget/desktop_aura/desktop_capture_client.h', 'widget/desktop_aura/desktop_cursor_loader_updater.h', 'widget/desktop_aura/desktop_cursor_loader_updater_aurax11.cc', 'widget/desktop_aura/desktop_cursor_loader_updater_aurax11.h', @@ -362,6 +365,8 @@ 'widget/desktop_aura/desktop_drag_drop_client_win.h', 'widget/desktop_aura/desktop_drop_target_win.cc', 'widget/desktop_aura/desktop_drop_target_win.h', + 'widget/desktop_aura/desktop_factory_ozone.cc', + 'widget/desktop_aura/desktop_factory_ozone.h', 'widget/desktop_aura/desktop_focus_rules.cc', 'widget/desktop_aura/desktop_focus_rules.h', 'widget/desktop_aura/desktop_layout_manager.cc', @@ -371,16 +376,20 @@ 'widget/desktop_aura/desktop_native_widget_aura.cc', 'widget/desktop_aura/desktop_native_widget_aura.h', 'widget/desktop_aura/desktop_root_window_host.h', + 'widget/desktop_aura/desktop_root_window_host_ozone.cc', 'widget/desktop_aura/desktop_root_window_host_win.cc', 'widget/desktop_aura/desktop_root_window_host_win.h', 'widget/desktop_aura/desktop_root_window_host_x11.cc', 'widget/desktop_aura/desktop_root_window_host_x11.h', 'widget/desktop_aura/desktop_screen.h', + 'widget/desktop_aura/desktop_screen_ozone.cc', 'widget/desktop_aura/desktop_screen_position_client.cc', 'widget/desktop_aura/desktop_screen_position_client.h', 'widget/desktop_aura/desktop_screen_win.cc', 'widget/desktop_aura/desktop_screen_win.h', 'widget/desktop_aura/desktop_screen_x11.cc', + 'widget/desktop_aura/scoped_tooltip_client.cc', + 'widget/desktop_aura/scoped_tooltip_client.h', 'widget/desktop_aura/x11_desktop_handler.cc', 'widget/desktop_aura/x11_desktop_handler.h', 'widget/desktop_aura/x11_desktop_window_move_client.cc', @@ -448,6 +457,7 @@ 'window/dialog_delegate.h', 'window/frame_background.cc', 'window/frame_background.h', + 'window/frame_buttons.h', 'window/native_frame_view.cc', 'window/native_frame_view.h', 'window/non_client_view.cc', @@ -475,14 +485,6 @@ 'widget/tooltip_manager_win.h', ], 'conditions': [ - ['OS=="mac"', { - 'sources/': [ - ['exclude', 'mouse_watcher.cc'], - ['exclude', 'controls/menu/'], - ['exclude', 'controls/scrollbar/'], - ['exclude', 'focus/accelerator_handler_aura.cc'], - ], - }], ['OS=="win"', { 'sources/': [ ['include', 'controls/menu/menu_insertion_delegate_win.h'], @@ -539,10 +541,13 @@ ['include', 'accessibility/native_view_accessibility_win.h'], ], }], - ['use_aura==1 and OS=="linux" and chromeos==0', { + ['OS=="linux" and chromeos==0', { 'dependencies': [ '../ui.gyp:shell_dialogs', - '../linux_ui/linux_ui.gyp:linux_ui', + ], + }, { # OS=="linux" and chromeos==0 + 'sources/': [ + ['exclude', 'linux_ui'], ], }], ['OS=="win"', { @@ -554,6 +559,10 @@ '../../third_party/wtl/include', ], 'link_settings': { + 'libraries': [ + '-limm32.lib', + '-loleacc.lib', + ], 'msvs_settings': { 'VCLinkerTool': { 'DelayLoadDLLs': [ @@ -614,6 +623,9 @@ 'test/test_widget_observer.h', 'test/views_test_base.cc', 'test/views_test_base.h', + 'test/widget_test.cc', + 'test/widget_test.h', + 'widget/root_view_test_helper.h', ], 'conditions': [ ['use_aura==1', { @@ -693,7 +705,7 @@ 'controls/button/custom_button_unittest.cc', 'controls/button/image_button_unittest.cc', 'controls/button/label_button_unittest.cc', - 'controls/combobox/native_combobox_views_unittest.cc', + 'controls/combobox/combobox_unittest.cc', 'controls/label_unittest.cc', 'controls/menu/menu_model_adapter_unittest.cc', 'controls/native/native_view_host_aura_unittest.cc', @@ -713,6 +725,7 @@ 'controls/textfield/native_textfield_views_unittest.cc', 'controls/textfield/textfield_views_model_unittest.cc', 'controls/tree/tree_view_unittest.cc', + 'corewm/capture_controller_unittest.cc', 'corewm/compound_event_filter_unittest.cc', 'corewm/cursor_manager_unittest.cc', 'corewm/focus_controller_unittest.cc', @@ -731,20 +744,21 @@ 'ime/input_method_bridge_unittest.cc', 'layout/box_layout_unittest.cc', 'layout/grid_layout_unittest.cc', + 'run_all_unittests.cc', 'touchui/touch_selection_controller_impl_unittest.cc', 'view_model_unittest.cc', 'view_model_utils_unittest.cc', 'view_unittest.cc', - 'window/dialog_client_view_unittest.cc', - 'window/dialog_delegate_unittest.cc', - 'widget/desktop_aura/desktop_capture_client_unittest.cc', + 'widget/desktop_aura/desktop_native_widget_aura_unittest.cc', 'widget/desktop_aura/desktop_screen_position_client_unittest.cc', 'widget/native_widget_aura_unittest.cc', 'widget/native_widget_unittest.cc', 'widget/native_widget_win_unittest.cc', + 'widget/root_view_unittest.cc', 'widget/widget_unittest.cc', 'widget/window_reorderer_unittest.cc', - 'run_all_unittests.cc', + 'window/dialog_client_view_unittest.cc', + 'window/dialog_delegate_unittest.cc', ], 'conditions': [ ['chromeos==0', { @@ -798,6 +812,11 @@ ['exclude', 'widget/window_reorderer_unittest.cc'] ], }], + ['use_ozone==1', { + 'sources!': [ + 'corewm/capture_controller_unittest.cc', + ], + }], ], }, # target_name: views_unittests { diff --git a/chromium/ui/views/widget/aero_tooltip_manager.cc b/chromium/ui/views/widget/aero_tooltip_manager.cc index b1719def27f..c54124c90bf 100644 --- a/chromium/ui/views/widget/aero_tooltip_manager.cc +++ b/chromium/ui/views/widget/aero_tooltip_manager.cc @@ -11,9 +11,9 @@ #include "base/bind.h" #include "base/message_loop/message_loop.h" #include "ui/base/l10n/l10n_util_win.h" -#include "ui/base/win/dpi.h" -#include "ui/base/win/hwnd_util.h" #include "ui/gfx/point.h" +#include "ui/gfx/win/dpi.h" +#include "ui/gfx/win/hwnd_util.h" namespace views { @@ -42,13 +42,13 @@ void AeroTooltipManager::OnMouse(UINT u_msg, WPARAM w_param, LPARAM l_param) { if (u_msg == WM_MOUSEMOVE || u_msg == WM_NCMOUSEMOVE) { gfx::Point mouse_pos_in_pixels(l_param); - gfx::Point mouse_pos = ui::win::ScreenToDIPPoint(mouse_pos_in_pixels); + gfx::Point mouse_pos = gfx::win::ScreenToDIPPoint(mouse_pos_in_pixels); if (u_msg == WM_NCMOUSEMOVE) { // NC message coordinates are in screen coordinates. POINT temp = mouse_pos_in_pixels.ToPOINT(); ::MapWindowPoints(HWND_DESKTOP, GetParent(), &temp, 1); mouse_pos_in_pixels.SetPoint(temp.x, temp.y); - mouse_pos = ui::win::ScreenToDIPPoint(mouse_pos_in_pixels); + mouse_pos = gfx::win::ScreenToDIPPoint(mouse_pos_in_pixels); } if (last_mouse_pos_ != mouse_pos) { last_mouse_pos_ = mouse_pos; diff --git a/chromium/ui/views/widget/desktop_aura/desktop_activation_client.cc b/chromium/ui/views/widget/desktop_aura/desktop_activation_client.cc deleted file mode 100644 index dc8f062cc32..00000000000 --- a/chromium/ui/views/widget/desktop_aura/desktop_activation_client.cc +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright (c) 2012 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 "ui/views/widget/desktop_aura/desktop_activation_client.h" - -#include "base/auto_reset.h" -#include "base/compiler_specific.h" -#include "ui/aura/client/activation_delegate.h" -#include "ui/aura/client/activation_change_observer.h" -#include "ui/aura/client/focus_client.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" - -namespace views { - -namespace { - -aura::Window* FindFocusableWindowFor(aura::Window* window) { - while (window && !window->CanFocus()) - window = window->parent(); - return window; -} - -} // namespace - -DesktopActivationClient::DesktopActivationClient(aura::RootWindow* root_window) - : root_window_(root_window), - current_active_(NULL), - updating_activation_(false), - observer_manager_(this) { - aura::client::GetFocusClient(root_window_)->AddObserver(this); - aura::client::SetActivationClient(root_window_, this); - root_window->AddPreTargetHandler(this); -} - -DesktopActivationClient::~DesktopActivationClient() { - root_window_->RemovePreTargetHandler(this); - aura::client::GetFocusClient(root_window_)->RemoveObserver(this); - aura::client::SetActivationClient(root_window_, NULL); -} - -void DesktopActivationClient::AddObserver( - aura::client::ActivationChangeObserver* observer) { - observers_.AddObserver(observer); -} - -void DesktopActivationClient::RemoveObserver( - aura::client::ActivationChangeObserver* observer) { - observers_.RemoveObserver(observer); -} - -void DesktopActivationClient::ActivateWindow(aura::Window* window) { - // Prevent recursion when called from focus. - if (updating_activation_) - return; - - base::AutoReset<bool> in_activate_window(&updating_activation_, true); - // Nothing may actually have changed. - if (current_active_ == window) - return; - // The stacking client may impose rules on what window configurations can be - // activated or deactivated. - if (window && !CanActivateWindow(window)) - return; - // Switch internal focus before we change the activation. Will probably cause - // recursion. - if (window && - !window->Contains(aura::client::GetFocusClient(window)-> - GetFocusedWindow())) { - aura::client::GetFocusClient(window)->FocusWindow(window); - } - - aura::Window* old_active = current_active_; - current_active_ = window; - if (window && !observer_manager_.IsObserving(window)) - observer_manager_.Add(window); - - FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver, - observers_, - OnWindowActivated(window, old_active)); - aura::client::ActivationChangeObserver* observer = - aura::client::GetActivationChangeObserver(old_active); - if (observer) - observer->OnWindowActivated(window, old_active); - observer = aura::client::GetActivationChangeObserver(window); - if (observer) - observer->OnWindowActivated(window, old_active); -} - -void DesktopActivationClient::DeactivateWindow(aura::Window* window) { - if (window == current_active_) - current_active_ = NULL; -} - -aura::Window* DesktopActivationClient::GetActiveWindow() { - return current_active_; -} - -aura::Window* DesktopActivationClient::GetActivatableWindow( - aura::Window* window) { - aura::Window* parent = window->parent(); - aura::Window* child = window; - while (parent) { - if (CanActivateWindow(child)) - return child; - // If |child| isn't activatable, but has transient parent, trace - // that path instead. - if (child->transient_parent()) - return GetActivatableWindow(child->transient_parent()); - parent = parent->parent(); - child = child->parent(); - } - return NULL; -} - -aura::Window* DesktopActivationClient::GetToplevelWindow(aura::Window* window) { - aura::Window* parent = window->parent(); - aura::Window* child = window; - aura::Window* root = child->GetRootWindow(); - while (parent) { - if (parent == root) - return child; - parent = parent->parent(); - child = child->parent(); - } - return NULL; -} - -bool DesktopActivationClient::OnWillFocusWindow(aura::Window* window, - const ui::Event* event) { - return CanActivateWindow(GetActivatableWindow(window)); -} - -void DesktopActivationClient::OnWindowDestroying(aura::Window* window) { - if (current_active_ == window) { - current_active_ = NULL; - FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver, - observers_, - OnWindowActivated(NULL, window)); - - // ash::ActivationController will also activate the next window here; we - // don't do this because that's the desktop environment's job. - } - observer_manager_.Remove(window); -} - -void DesktopActivationClient::OnWindowFocused(aura::Window* gained_focus, - aura::Window* lost_focus) { - if (gained_focus) - ActivateWindow(GetActivatableWindow(gained_focus)); -} - -bool DesktopActivationClient::CanActivateWindow(aura::Window* window) const { - return window && - window->IsVisible() && - (!aura::client::GetActivationDelegate(window) || - aura::client::GetActivationDelegate(window)->ShouldActivate()); -} - -void DesktopActivationClient::OnKeyEvent(ui::KeyEvent* event) { -} - -void DesktopActivationClient::OnMouseEvent(ui::MouseEvent* event) { - if (event->type() == ui::ET_MOUSE_PRESSED) - FocusWindowWithEvent(event); -} - -void DesktopActivationClient::OnScrollEvent(ui::ScrollEvent* event) { -} - -void DesktopActivationClient::OnTouchEvent(ui::TouchEvent* event) { -} - -void DesktopActivationClient::OnGestureEvent(ui::GestureEvent* event) { - if (event->type() == ui::ET_GESTURE_BEGIN && - event->details().touch_points() == 1) { - FocusWindowWithEvent(event); - } -} - -void DesktopActivationClient::FocusWindowWithEvent(const ui::Event* event) { - aura::Window* window = static_cast<aura::Window*>(event->target()); - if (GetActiveWindow() != window) { - aura::client::GetFocusClient(window)->FocusWindow( - FindFocusableWindowFor(window)); - } -} - -} // namespace views diff --git a/chromium/ui/views/widget/desktop_aura/desktop_activation_client.h b/chromium/ui/views/widget/desktop_aura/desktop_activation_client.h deleted file mode 100644 index b34181792ff..00000000000 --- a/chromium/ui/views/widget/desktop_aura/desktop_activation_client.h +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_DESTKOP_ACTIVATION_CLIENT_H_ -#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESTKOP_ACTIVATION_CLIENT_H_ - -#include "base/basictypes.h" -#include "base/observer_list.h" -#include "base/scoped_observer.h" -#include "ui/aura/client/activation_client.h" -#include "ui/aura/client/focus_change_observer.h" -#include "ui/aura/env_observer.h" -#include "ui/aura/root_window_observer.h" -#include "ui/aura/window_observer.h" -#include "ui/views/views_export.h" - -namespace aura { -class FocusManager; -class RootWindow; - -namespace client { -class ActivationChangeObserver; -} -} - -namespace views { - -// An activation client that handles activation events in a single -// RootWindow. Used only on the Desktop where there can be multiple RootWindow -// objects. -class VIEWS_EXPORT DesktopActivationClient - : public aura::client::ActivationClient, - public aura::WindowObserver, - public ui::EventHandler, - public aura::client::FocusChangeObserver { - public: - explicit DesktopActivationClient(aura::RootWindow* root_window); - virtual ~DesktopActivationClient(); - - // ActivationClient: - virtual void AddObserver( - aura::client::ActivationChangeObserver* observer) OVERRIDE; - virtual void RemoveObserver( - aura::client::ActivationChangeObserver* observer) OVERRIDE; - virtual void ActivateWindow(aura::Window* window) OVERRIDE; - virtual void DeactivateWindow(aura::Window* window) OVERRIDE; - virtual aura::Window* GetActiveWindow() OVERRIDE; - virtual aura::Window* GetActivatableWindow(aura::Window* window) OVERRIDE; - virtual aura::Window* GetToplevelWindow(aura::Window* window) OVERRIDE; - virtual bool OnWillFocusWindow(aura::Window* window, - const ui::Event* event) OVERRIDE; - virtual bool CanActivateWindow(aura::Window* window) const OVERRIDE; - - // Overridden from aura::WindowObserver: - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - - // Overridden from aura::client::FocusChangeObserver: - virtual void OnWindowFocused(aura::Window* gained_focus, - aura::Window* lost_focus) OVERRIDE; - - // Overridden from ui::EventHandler: - virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; - virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; - virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE; - virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE; - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; - - private: - void FocusWindowWithEvent(const ui::Event* event); - - aura::RootWindow* root_window_; - - // The current active window. - aura::Window* current_active_; - - // True inside ActivateWindow(). Used to prevent recursion of focus - // change notifications causing activation. - bool updating_activation_; - - ObserverList<aura::client::ActivationChangeObserver> observers_; - - ScopedObserver<aura::Window, aura::WindowObserver> observer_manager_; - - DISALLOW_COPY_AND_ASSIGN(DesktopActivationClient); -}; - -} // namespace views - -#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_DESTKOP_ACTIVATION_CLIENT_H_ diff --git a/chromium/ui/views/widget/desktop_aura/desktop_capture_client.cc b/chromium/ui/views/widget/desktop_aura/desktop_capture_client.cc deleted file mode 100644 index bf89a4eb916..00000000000 --- a/chromium/ui/views/widget/desktop_aura/desktop_capture_client.cc +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2012 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 "ui/views/widget/desktop_aura/desktop_capture_client.h" - -#include "ui/aura/root_window.h" - -namespace views { - -std::set<DesktopCaptureClient*> DesktopCaptureClient::live_capture_clients_; - -DesktopCaptureClient::DesktopCaptureClient(aura::RootWindow* root_window) - : root_window_(root_window), - capture_window_(NULL) { - aura::client::SetCaptureClient(root_window_, this); - live_capture_clients_.insert(this); -} - -DesktopCaptureClient::~DesktopCaptureClient() { - live_capture_clients_.erase(this); - aura::client::SetCaptureClient(root_window_, NULL); -} - -void DesktopCaptureClient::SetCapture(aura::Window* window) { - if (capture_window_ == window) - return; - if (window) { - // If we're actually starting capture, then cancel any touches/gestures - // that aren't already locked to the new window, and transfer any on the - // old capture window to the new one. When capture is released we have no - // distinction between the touches/gestures that were in the window all - // along (and so shouldn't be canceled) and those that got moved, so - // just leave them all where they are. - for (std::set<DesktopCaptureClient*>::iterator it = - live_capture_clients_.begin(); it != live_capture_clients_.end(); - ++it) { - (*it)->root_window_->gesture_recognizer()->TransferEventsTo( - capture_window_, window); - } - } - aura::Window* old_capture_window = GetCaptureWindow(); - capture_window_ = window; - - if (capture_window_) { - root_window_->SetNativeCapture(); - - for (std::set<DesktopCaptureClient*>::iterator it = - live_capture_clients_.begin(); it != live_capture_clients_.end(); - ++it) { - if (*it != this) - (*it)->OnOtherCaptureClientTookCapture(); - } - } else { - root_window_->ReleaseNativeCapture(); - } - - root_window_->UpdateCapture(old_capture_window, capture_window_); -} - -void DesktopCaptureClient::ReleaseCapture(aura::Window* window) { - if (capture_window_ != window) - return; - SetCapture(NULL); -} - -aura::Window* DesktopCaptureClient::GetCaptureWindow() { - for (std::set<DesktopCaptureClient*>::iterator it = - live_capture_clients_.begin(); it != live_capture_clients_.end(); - ++it) { - if ((*it)->capture_window_) - return (*it)->capture_window_; - } - return NULL; -} - -void DesktopCaptureClient::OnOtherCaptureClientTookCapture() { - if (capture_window_ == NULL) { - // While RootWindow may not technically have capture, it will store state - // that needs to be cleared on capture changed regarding mouse up/down. - root_window_->ClearMouseHandlers(); - } - else { - SetCapture(NULL); - } -} - -} // namespace views diff --git a/chromium/ui/views/widget/desktop_aura/desktop_capture_client.h b/chromium/ui/views/widget/desktop_aura/desktop_capture_client.h deleted file mode 100644 index ba126826196..00000000000 --- a/chromium/ui/views/widget/desktop_aura/desktop_capture_client.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 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. - -#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_CAPTURE_CLIENT_H_ -#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_CAPTURE_CLIENT_H_ - -#include <set> - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "ui/aura/client/capture_client.h" -#include "ui/views/views_export.h" - -namespace views { - -// A capture client which will collaborate with all other capture clients of -// its class. When capture is changed in an instance of this capture client, -// capture is released in all other windows. -class VIEWS_EXPORT DesktopCaptureClient : public aura::client::CaptureClient { - public: - explicit DesktopCaptureClient(aura::RootWindow* root_window); - virtual ~DesktopCaptureClient(); - - // Overridden from client::CaptureClient: - virtual void SetCapture(aura::Window* window) OVERRIDE; - virtual void ReleaseCapture(aura::Window* window) OVERRIDE; - virtual aura::Window* GetCaptureWindow() OVERRIDE; - - private: - // Called when another instance of the capture client takes capture. - void OnOtherCaptureClientTookCapture(); - - aura::RootWindow* root_window_; - aura::Window* capture_window_; - - static std::set<DesktopCaptureClient*> live_capture_clients_; - - DISALLOW_COPY_AND_ASSIGN(DesktopCaptureClient); -}; - -} // namespace views - -#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_CAPTURE_CLIENT_H_ diff --git a/chromium/ui/views/widget/desktop_aura/desktop_capture_client_unittest.cc b/chromium/ui/views/widget/desktop_aura/desktop_capture_client_unittest.cc deleted file mode 100644 index d96c4456724..00000000000 --- a/chromium/ui/views/widget/desktop_aura/desktop_capture_client_unittest.cc +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright (c) 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 "ui/views/widget/desktop_aura/desktop_capture_client.h" - -#include "ui/aura/root_window.h" -#include "ui/aura/test/aura_test_base.h" -#include "ui/aura/test/test_screen.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/base/events/event.h" -#include "ui/views/test/views_test_base.h" -#include "ui/views/view.h" -#include "ui/views/widget/desktop_aura/desktop_screen_position_client.h" -#include "ui/views/widget/root_view.h" -#include "ui/views/widget/widget.h" - -namespace views { - -typedef ViewsTestBase ViewTest; - -class DesktopCaptureClientTest : public aura::test::AuraTestBase { - public: - virtual void SetUp() OVERRIDE { - AuraTestBase::SetUp(); - desktop_capture_client_.reset(new DesktopCaptureClient(root_window())); - - second_root_.reset(new aura::RootWindow( - aura::RootWindow::CreateParams(gfx::Rect(0, 0, 800, 600)))); - second_root_->Init(); - second_root_->Show(); - second_root_->SetHostSize(gfx::Size(800, 600)); - second_desktop_capture_client_.reset( - new DesktopCaptureClient(second_root_.get())); - - desktop_position_client_.reset(new DesktopScreenPositionClient()); - aura::client::SetScreenPositionClient(root_window(), - desktop_position_client_.get()); - - second_desktop_position_client_.reset(new DesktopScreenPositionClient()); - aura::client::SetScreenPositionClient( - second_root_.get(), - second_desktop_position_client_.get()); - } - - virtual void TearDown() OVERRIDE { - RunAllPendingInMessageLoop(); - - second_desktop_position_client_.reset(); - second_desktop_capture_client_.reset(); - - // Kill any active compositors before we hit the compositor shutdown paths. - second_root_.reset(); - - desktop_position_client_.reset(); - desktop_capture_client_.reset(); - - AuraTestBase::TearDown(); - } - - scoped_ptr<DesktopCaptureClient> desktop_capture_client_; - scoped_ptr<aura::RootWindow> second_root_; - scoped_ptr<DesktopCaptureClient> second_desktop_capture_client_; - scoped_ptr<aura::client::ScreenPositionClient> desktop_position_client_; - scoped_ptr<aura::client::ScreenPositionClient> - second_desktop_position_client_; -}; - -// Makes sure that internal details that are set on mouse down (such as -// mouse_pressed_handler()) are cleared when another root window takes capture. -TEST_F(DesktopCaptureClientTest, ResetMouseEventHandlerOnCapture) { - // Create a window inside the RootWindow. - scoped_ptr<aura::Window> w1(CreateNormalWindow(1, root_window(), NULL)); - - // Make a synthesized mouse down event. Ensure that the RootWindow will - // dispatch further mouse events to |w1|. - ui::MouseEvent mouse_pressed_event(ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), - gfx::Point(5, 5), 0); - root_window()->AsRootWindowHostDelegate()->OnHostMouseEvent( - &mouse_pressed_event); - EXPECT_EQ(w1.get(), root_window()->mouse_pressed_handler()); - - // Build a window in the second RootWindow. - scoped_ptr<aura::Window> w2(CreateNormalWindow(2, second_root_.get(), NULL)); - - // The act of having the second window take capture should clear out mouse - // pressed handler in the first RootWindow. - w2->SetCapture(); - EXPECT_EQ(NULL, root_window()->mouse_pressed_handler()); -} - -// Makes sure that when one window gets capture, it forces the release on the -// other. This is needed has to be handled explicitly on Linux, and is a sanity -// check on Windows. -TEST_F(DesktopCaptureClientTest, ResetOtherWindowCaptureOnCapture) { - // Create a window inside the RootWindow. - scoped_ptr<aura::Window> w1(CreateNormalWindow(1, root_window(), NULL)); - w1->SetCapture(); - // Both capture clients should return the same capture window. - EXPECT_EQ(w1.get(), desktop_capture_client_->GetCaptureWindow()); - EXPECT_EQ(w1.get(), second_desktop_capture_client_->GetCaptureWindow()); - - // Build a window in the second RootWindow and give it capture. Both capture - // clients should return the same capture window. - scoped_ptr<aura::Window> w2(CreateNormalWindow(2, second_root_.get(), NULL)); - w2->SetCapture(); - EXPECT_EQ(w2.get(), desktop_capture_client_->GetCaptureWindow()); - EXPECT_EQ(w2.get(), second_desktop_capture_client_->GetCaptureWindow()); -} - -// This class provides functionality to verify whether the View instance -// received the gesture event. -class DesktopViewInputTest : public View { - public: - DesktopViewInputTest() - : received_gesture_event_(false) {} - - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { - received_gesture_event_ = true; - return View::OnGestureEvent(event); - } - - // Resets state maintained by this class. - void Reset() { - received_gesture_event_ = false; - } - - bool received_gesture_event() const { return received_gesture_event_; } - - private: - bool received_gesture_event_; - - DISALLOW_COPY_AND_ASSIGN(DesktopViewInputTest); -}; - -// Tests aura::Window capture and whether gesture events are sent to the window -// which has capture. -// The test case creates two visible widgets and sets capture to the underlying -// aura::Windows one by one. It then sends a gesture event and validates whether -// the window which had capture receives the gesture. -TEST_F(ViewTest, CaptureWindowInputEventTest) { - scoped_ptr<DesktopCaptureClient> desktop_capture_client1; - scoped_ptr<DesktopCaptureClient> desktop_capture_client2; - scoped_ptr<aura::client::ScreenPositionClient> desktop_position_client1; - scoped_ptr<aura::client::ScreenPositionClient> desktop_position_client2; - - scoped_ptr<Widget> widget1(new Widget()); - Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.bounds = gfx::Rect(50, 50, 650, 650); - widget1->Init(params); - internal::RootView* root1 = - static_cast<internal::RootView*>(widget1->GetRootView()); - - desktop_capture_client1.reset(new DesktopCaptureClient( - widget1->GetNativeView()->GetRootWindow())); - desktop_position_client1.reset(new DesktopScreenPositionClient()); - aura::client::SetScreenPositionClient( - widget1->GetNativeView()->GetRootWindow(), - desktop_position_client1.get()); - - DesktopViewInputTest* v1 = new DesktopViewInputTest(); - v1->SetBoundsRect(gfx::Rect(0, 0, 300, 300)); - root1->AddChildView(v1); - widget1->Show(); - - scoped_ptr<Widget> widget2(new Widget()); - - params = CreateParams(Widget::InitParams::TYPE_POPUP); - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.bounds = gfx::Rect(50, 50, 650, 650); - widget2->Init(params); - - internal::RootView* root2 = - static_cast<internal::RootView*>(widget2->GetRootView()); - desktop_capture_client2.reset(new DesktopCaptureClient( - widget2->GetNativeView()->GetRootWindow())); - desktop_position_client2.reset(new DesktopScreenPositionClient()); - aura::client::SetScreenPositionClient( - widget2->GetNativeView()->GetRootWindow(), - desktop_position_client2.get()); - - DesktopViewInputTest* v2 = new DesktopViewInputTest(); - v2->SetBoundsRect(gfx::Rect(0, 0, 300, 300)); - root2->AddChildView(v2); - widget2->Show(); - - EXPECT_FALSE(widget1->GetNativeView()->HasCapture()); - EXPECT_FALSE(widget2->GetNativeView()->HasCapture()); - EXPECT_EQ(desktop_capture_client1->GetCaptureWindow(), - reinterpret_cast<aura::Window*>(0)); - EXPECT_EQ(desktop_capture_client2->GetCaptureWindow(), - reinterpret_cast<aura::Window*>(0)); - - widget1->GetNativeView()->SetCapture(); - EXPECT_TRUE(widget1->GetNativeView()->HasCapture()); - EXPECT_FALSE(widget2->GetNativeView()->HasCapture()); - EXPECT_EQ(desktop_capture_client1->GetCaptureWindow(), - widget1->GetNativeView()); - EXPECT_EQ(desktop_capture_client2->GetCaptureWindow(), - widget1->GetNativeView()); - - ui::GestureEvent g1(ui::ET_GESTURE_LONG_PRESS, 80, 80, 0, - base::TimeDelta(), - ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS, - 0.0f, 0.0f), 0); - root1->DispatchGestureEvent(&g1); - EXPECT_TRUE(v1->received_gesture_event()); - EXPECT_FALSE(v2->received_gesture_event()); - v1->Reset(); - v2->Reset(); - - widget2->GetNativeView()->SetCapture(); - - EXPECT_FALSE(widget1->GetNativeView()->HasCapture()); - EXPECT_TRUE(widget2->GetNativeView()->HasCapture()); - EXPECT_EQ(desktop_capture_client1->GetCaptureWindow(), - widget2->GetNativeView()); - EXPECT_EQ(desktop_capture_client2->GetCaptureWindow(), - widget2->GetNativeView()); - - root2->DispatchGestureEvent(&g1); - EXPECT_TRUE(v2->received_gesture_event()); - EXPECT_FALSE(v1->received_gesture_event()); - - widget1->CloseNow(); - widget2->CloseNow(); - RunPendingMessages(); -} - -} // namespace views diff --git a/chromium/ui/views/widget/desktop_aura/desktop_cursor_loader_updater_aurax11.cc b/chromium/ui/views/widget/desktop_aura/desktop_cursor_loader_updater_aurax11.cc index e771f69be29..88f219300e0 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_cursor_loader_updater_aurax11.cc +++ b/chromium/ui/views/widget/desktop_aura/desktop_cursor_loader_updater_aurax11.cc @@ -35,8 +35,12 @@ void LoadImageCursors(float device_scale_factor, ui::CursorLoader* loader) { int resource_id; gfx::Point point; for (size_t i = 0; i < arraysize(kImageCursorIds); ++i) { - bool success = ui::GetCursorDataFor(kImageCursorIds[i], device_scale_factor, - &resource_id, &point); + bool success = ui::GetCursorDataFor( + ui::CURSOR_SET_NORMAL, // Not support custom cursor set. + kImageCursorIds[i], + device_scale_factor, + &resource_id, + &point); DCHECK(success); loader->LoadImageCursor(kImageCursorIds[i], resource_id, point); } diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc index 1870e11f5b8..bc0e6e9157c 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc +++ b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc @@ -15,9 +15,9 @@ #include "ui/base/dragdrop/drag_drop_types.h" #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h" -#include "ui/base/events/event.h" #include "ui/base/x/selection_utils.h" #include "ui/base/x/x11_util.h" +#include "ui/events/event.h" #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h" using aura::client::DragDropDelegate; @@ -236,14 +236,13 @@ DesktopDragDropClientAuraX11::X11DragContext::X11DragContext( if (!client) { // The window doesn't have a DesktopDragDropClientAuraX11, that means it's // created by some other process. Listen for messages on it. - base::MessagePumpAuraX11::Current()->AddDispatcherForWindow( + base::MessagePumpX11::Current()->AddDispatcherForWindow( this, source_window_); - XSelectInput(base::MessagePumpAuraX11::GetDefaultXDisplay(), - source_window_, PropertyChangeMask); + XSelectInput(gfx::GetXDisplay(), source_window_, PropertyChangeMask); // We must perform a full sync here because we could be racing // |source_window_|. - XSync(base::MessagePumpAuraX11::GetDefaultXDisplay(), False); + XSync(gfx::GetXDisplay(), False); } else { // This drag originates from an aura window within our process. This means // that we can shortcut the X11 server and ask the owning SelectionOwner @@ -260,7 +259,7 @@ DesktopDragDropClientAuraX11::X11DragContext::~X11DragContext() { DesktopDragDropClientAuraX11::GetForWindow(source_window_); if (!client) { // Unsubscribe from message events. - base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow( + base::MessagePumpX11::Current()->RemoveDispatcherForWindow( source_window_); } } @@ -289,7 +288,7 @@ void DesktopDragDropClientAuraX11::X11DragContext::RequestNextTarget() { ::Atom target = unfetched_targets_.back(); unfetched_targets_.pop_back(); - XConvertSelection(base::MessagePumpAuraX11::GetDefaultXDisplay(), + XConvertSelection(gfx::GetXDisplay(), atom_cache_->GetAtom(kXdndSelection), target, atom_cache_->GetAtom(kChromiumDragReciever), diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h index 2dee7305f2f..0ebbb9511eb 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h +++ b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h @@ -17,6 +17,7 @@ #include "base/memory/scoped_ptr.h" #include "ui/aura/client/drag_drop_client.h" #include "ui/aura/window_observer.h" +#include "ui/base/cursor/cursor.h" #include "ui/base/x/x11_atom_cache.h" #include "ui/gfx/point.h" #include "ui/views/views_export.h" diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drop_target_win.cc b/chromium/ui/views/widget/desktop_aura/desktop_drop_target_win.cc index d3a01f3c208..c9c7540b5cb 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_drop_target_win.cc +++ b/chromium/ui/views/widget/desktop_aura/desktop_drop_target_win.cc @@ -4,13 +4,15 @@ #include "ui/views/widget/desktop_aura/desktop_drop_target_win.h" +#include "base/win/win_util.h" #include "ui/aura/client/drag_drop_client.h" #include "ui/aura/client/drag_drop_delegate.h" #include "ui/aura/window.h" #include "ui/aura/root_window.h" #include "ui/base/dragdrop/drag_drop_types.h" #include "ui/base/dragdrop/os_exchange_data_provider_win.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" +#include "ui/events/event_constants.h" using aura::client::DragDropDelegate; using ui::OSExchangeData; @@ -121,6 +123,11 @@ void DesktopDropTargetWin::Translate( location, root_location, ui::DragDropTypes::DropEffectToDragOperation(effect))); + int flags = 0; + flags |= base::win::IsAltPressed() ? ui::EF_ALT_DOWN : ui::EF_NONE; + flags |= base::win::IsShiftPressed() ? ui::EF_SHIFT_DOWN : ui::EF_NONE; + flags |= base::win::IsCtrlPressed() ? ui::EF_CONTROL_DOWN : ui::EF_NONE; + (*event)->set_flags(flags); if (target_window_changed) (*delegate)->OnDragEntered(*event->get()); } diff --git a/chromium/ui/views/widget/desktop_aura/desktop_factory_ozone.cc b/chromium/ui/views/widget/desktop_aura/desktop_factory_ozone.cc new file mode 100644 index 00000000000..e0a44890bc2 --- /dev/null +++ b/chromium/ui/views/widget/desktop_aura/desktop_factory_ozone.cc @@ -0,0 +1,29 @@ +// 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 "ui/views/widget/desktop_aura/desktop_factory_ozone.h" + +#include "base/logging.h" + +namespace views { + +// static +DesktopFactoryOzone* DesktopFactoryOzone::impl_ = NULL; + +DesktopFactoryOzone::DesktopFactoryOzone() { +} + +DesktopFactoryOzone::~DesktopFactoryOzone() { +} + +DesktopFactoryOzone* DesktopFactoryOzone::GetInstance() { + CHECK(impl_) << "DesktopFactoryOzone accessed before constructed"; + return impl_; +} + +void DesktopFactoryOzone::SetInstance(DesktopFactoryOzone* impl) { + impl_ = impl; +} + +} // namespace views diff --git a/chromium/ui/views/widget/desktop_aura/desktop_factory_ozone.h b/chromium/ui/views/widget/desktop_aura/desktop_factory_ozone.h new file mode 100644 index 00000000000..18cf36e8698 --- /dev/null +++ b/chromium/ui/views/widget/desktop_aura/desktop_factory_ozone.h @@ -0,0 +1,46 @@ +// 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. + +#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_FACTORY_OZONE_H_ +#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_FACTORY_OZONE_H_ + +#include "ui/views/views_export.h" + +namespace gfx { +class Rect; +} + +namespace views { +class DesktopNativeWidgetAura; +class DesktopRootWindowHost; + +namespace internal { +class NativeWidgetDelegate; +} + +class VIEWS_EXPORT DesktopFactoryOzone { + public: + DesktopFactoryOzone(); + virtual ~DesktopFactoryOzone(); + + // Returns the instance. + static DesktopFactoryOzone* GetInstance(); + + // Sets the implementation delegate. Ownership is retained by the caller. + static void SetInstance(DesktopFactoryOzone* impl); + + // Delegates implementation of DesktopRootWindowHost::Create externally to + // Ozone implementation. + virtual DesktopRootWindowHost* CreateRootWindowHost( + internal::NativeWidgetDelegate* native_widget_delegate, + DesktopNativeWidgetAura* desktop_native_widget_aura, + const gfx::Rect& initial_bounds) = 0; + + private: + static DesktopFactoryOzone* impl_; // not owned +}; + +} // namespace views + +#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_FACTORY_OZONE_H_ diff --git a/chromium/ui/views/widget/desktop_aura/desktop_focus_rules.cc b/chromium/ui/views/widget/desktop_aura/desktop_focus_rules.cc index 54894f8dc9f..96634f06d57 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_focus_rules.cc +++ b/chromium/ui/views/widget/desktop_aura/desktop_focus_rules.cc @@ -9,12 +9,16 @@ namespace views { -DesktopFocusRules::DesktopFocusRules() {} +DesktopFocusRules::DesktopFocusRules(aura::Window* content_window) + : content_window_(content_window) {} + DesktopFocusRules::~DesktopFocusRules() {} bool DesktopFocusRules::SupportsChildActivation(aura::Window* window) const { - // In Desktop-Aura, only children of the RootWindow are activatable. - return window->GetRootWindow() == window; + // In Desktop-Aura, only the content_window or children of the RootWindow are + // activatable. + return window == content_window_->parent() || + window->GetRootWindow() == window; } } // namespace views diff --git a/chromium/ui/views/widget/desktop_aura/desktop_focus_rules.h b/chromium/ui/views/widget/desktop_aura/desktop_focus_rules.h index a7db8c2504f..bb12b1ecf31 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_focus_rules.h +++ b/chromium/ui/views/widget/desktop_aura/desktop_focus_rules.h @@ -11,13 +11,17 @@ namespace views { class DesktopFocusRules : public corewm::BaseFocusRules { public: - DesktopFocusRules(); + explicit DesktopFocusRules(aura::Window* content_window); virtual ~DesktopFocusRules(); private: // Overridden from corewm::BaseFocusRules: virtual bool SupportsChildActivation(aura::Window* window) const OVERRIDE; + // The content window. This is an activatable window even though it is a + // child. + aura::Window* content_window_; + DISALLOW_COPY_AND_ASSIGN(DesktopFocusRules); }; diff --git a/chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc b/chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc index a9b902dee46..eed97f32af5 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc +++ b/chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc @@ -68,6 +68,11 @@ void DesktopNativeCursorManager::SetVisibility( root_window_->OnCursorVisibilityChanged(visible); } +void DesktopNativeCursorManager::SetCursorSet( + ui::CursorSetType cursor_set, + views::corewm::NativeCursorManagerDelegate* delegate) { + NOTIMPLEMENTED(); +} void DesktopNativeCursorManager::SetScale( float scale, diff --git a/chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h b/chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h index f6a800bfb9f..563131d92cc 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h +++ b/chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h @@ -49,6 +49,9 @@ class VIEWS_EXPORT DesktopNativeCursorManager virtual void SetVisibility( bool visible, views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE; + virtual void SetCursorSet( + ui::CursorSetType cursor_set, + views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE; virtual void SetScale( float scale, views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE; diff --git a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc index 207e655e0e6..d5ed686ec1b 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc +++ b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc @@ -23,19 +23,21 @@ #include "ui/gfx/screen.h" #include "ui/gfx/size_conversions.h" #include "ui/native_theme/native_theme.h" +#include "ui/views/corewm/capture_controller.h" #include "ui/views/corewm/compound_event_filter.h" #include "ui/views/corewm/corewm_switches.h" #include "ui/views/corewm/input_method_event_filter.h" #include "ui/views/corewm/shadow_controller.h" #include "ui/views/corewm/shadow_types.h" -#include "ui/views/corewm/tooltip_controller.h" #include "ui/views/corewm/visibility_controller.h" #include "ui/views/corewm/window_modality_controller.h" #include "ui/views/drag_utils.h" #include "ui/views/ime/input_method.h" #include "ui/views/ime/input_method_bridge.h" #include "ui/views/widget/desktop_aura/desktop_root_window_host.h" +#include "ui/views/widget/desktop_aura/scoped_tooltip_client.h" #include "ui/views/widget/drop_helper.h" +#include "ui/views/widget/native_widget_aura.h" #include "ui/views/widget/native_widget_aura_window_observer.h" #include "ui/views/widget/root_view.h" #include "ui/views/widget/tooltip_manager_aura.h" @@ -54,38 +56,40 @@ DEFINE_WINDOW_PROPERTY_KEY(DesktopNativeWidgetAura*, namespace { -// This class provides functionality to create a top level fullscreen widget to -// host a child window. -class DesktopNativeWidgetFullscreenHandler : public aura::WindowObserver { +// This class provides functionality to create a top level widget to host a +// child window. +class DesktopNativeWidgetTopLevelHandler : public aura::WindowObserver { public: - // This function creates a full screen widget with the bounds passed in - // which eventually becomes the parent of the child window passed in. + // This function creates a widget with the bounds passed in which eventually + // becomes the parent of the child window passed in. static aura::Window* CreateParentWindow(aura::Window* child_window, - const gfx::Rect& bounds) { - // This instance will get deleted when the fullscreen widget is destroyed. - DesktopNativeWidgetFullscreenHandler* full_screen_handler = - new DesktopNativeWidgetFullscreenHandler; + const gfx::Rect& bounds, + bool full_screen) { + // This instance will get deleted when the widget is destroyed. + DesktopNativeWidgetTopLevelHandler* top_level_handler = + new DesktopNativeWidgetTopLevelHandler; child_window->SetBounds(gfx::Rect(bounds.size())); Widget::InitParams init_params; - init_params.type = Widget::InitParams::TYPE_WINDOW; + init_params.type = full_screen ? Widget::InitParams::TYPE_WINDOW : + Widget::InitParams::TYPE_POPUP; init_params.bounds = bounds; init_params.ownership = Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET; init_params.layer_type = ui::LAYER_NOT_DRAWN; - - // This widget instance will get deleted when the fullscreen window is + init_params.can_activate = full_screen; + // This widget instance will get deleted when the window is // destroyed. - full_screen_handler->full_screen_widget_ = new Widget(); - full_screen_handler->full_screen_widget_->Init(init_params); + top_level_handler->top_level_widget_ = new Widget(); + top_level_handler->top_level_widget_->Init(init_params); - full_screen_handler->full_screen_widget_->SetFullscreen(true); - full_screen_handler->full_screen_widget_->Show(); + top_level_handler->top_level_widget_->SetFullscreen(full_screen); + top_level_handler->top_level_widget_->Show(); aura::Window* native_window = - full_screen_handler->full_screen_widget_->GetNativeView(); - child_window->AddObserver(full_screen_handler); - native_window->AddObserver(full_screen_handler); + top_level_handler->top_level_widget_->GetNativeView(); + child_window->AddObserver(top_level_handler); + native_window->AddObserver(top_level_handler); return native_window; } @@ -95,33 +99,33 @@ class DesktopNativeWidgetFullscreenHandler : public aura::WindowObserver { // If the widget is being destroyed by the OS then we should not try and // destroy it again. - if (full_screen_widget_ && - window == full_screen_widget_->GetNativeView()) { - full_screen_widget_ = NULL; + if (top_level_widget_ && + window == top_level_widget_->GetNativeView()) { + top_level_widget_ = NULL; return; } - if (full_screen_widget_) { - DCHECK(full_screen_widget_->GetNativeView()); - full_screen_widget_->GetNativeView()->RemoveObserver(this); - // When we receive a notification that the child of the fullscreen window - // created above is being destroyed we go ahead and initiate the - // destruction of the corresponding widget. - full_screen_widget_->Close(); - full_screen_widget_ = NULL; + if (top_level_widget_) { + DCHECK(top_level_widget_->GetNativeView()); + top_level_widget_->GetNativeView()->RemoveObserver(this); + // When we receive a notification that the child of the window created + // above is being destroyed we go ahead and initiate the destruction of + // the corresponding widget. + top_level_widget_->Close(); + top_level_widget_ = NULL; } delete this; } private: - DesktopNativeWidgetFullscreenHandler() - : full_screen_widget_(NULL) {} + DesktopNativeWidgetTopLevelHandler() + : top_level_widget_(NULL) {} - virtual ~DesktopNativeWidgetFullscreenHandler() {} + virtual ~DesktopNativeWidgetTopLevelHandler() {} - Widget* full_screen_widget_; + Widget* top_level_widget_; - DISALLOW_COPY_AND_ASSIGN(DesktopNativeWidgetFullscreenHandler); + DISALLOW_COPY_AND_ASSIGN(DesktopNativeWidgetTopLevelHandler); }; class DesktopNativeWidgetAuraStackingClient : @@ -139,10 +143,18 @@ class DesktopNativeWidgetAuraStackingClient : virtual aura::Window* GetDefaultParent(aura::Window* context, aura::Window* window, const gfx::Rect& bounds) OVERRIDE { - if (window->GetProperty(aura::client::kShowStateKey) == - ui::SHOW_STATE_FULLSCREEN) { - return DesktopNativeWidgetFullscreenHandler::CreateParentWindow(window, - bounds); + bool full_screen = window->GetProperty(aura::client::kShowStateKey) == + ui::SHOW_STATE_FULLSCREEN; + bool is_menu = false; + // TODO(erg): We need to be able to spawn and deal with toplevel windows if + // we want the popups to extend past our window + // bounds. http://crbug.com/288988 +#if !defined(OS_LINUX) + is_menu = window->type() == aura::client::WINDOW_TYPE_MENU; +#endif + if (full_screen || is_menu) { + return DesktopNativeWidgetTopLevelHandler::CreateParentWindow( + window, bounds, full_screen); } return root_window_; } @@ -165,6 +177,7 @@ DesktopNativeWidgetAura::DesktopNativeWidgetAura( can_activate_(true), desktop_root_window_host_(NULL), window_(new aura::Window(this)), + content_window_container_(NULL), native_widget_delegate_(delegate), last_drop_operation_(ui::DragDropTypes::DRAG_NONE), restore_focus_on_activate_(false), @@ -218,6 +231,42 @@ void DesktopNativeWidgetAura::InstallInputMethodEventFilter( root_window_event_filter_->AddHandler(input_method_event_filter_.get()); } +void DesktopNativeWidgetAura::CreateCaptureClient(aura::RootWindow* root) { + DCHECK(!capture_client_.get()); + capture_client_.reset(new corewm::ScopedCaptureClient(root)); +} + +void DesktopNativeWidgetAura::HandleActivationChanged(bool active) { + native_widget_delegate_->OnNativeWidgetActivationChanged(active); + aura::client::ActivationClient* activation_client = + aura::client::GetActivationClient(root_window_.get()); + if (!activation_client) + return; + if (active) { + if (GetWidget()->HasFocusManager()) { + // This function can be called before the focus manager has had a + // chance to set the focused view. In which case we should get the + // last focused view. + View* view_for_activation = + GetWidget()->GetFocusManager()->GetFocusedView() ? + GetWidget()->GetFocusManager()->GetFocusedView() : + GetWidget()->GetFocusManager()->GetStoredFocusView(); + if (!view_for_activation) + view_for_activation = GetWidget()->GetRootView(); + activation_client->ActivateWindow( + view_for_activation->GetWidget()->GetNativeView()); + } + } else { + // If we're not active we need to deactivate the corresponding + // aura::Window. This way if a child widget is active it gets correctly + // deactivated (child widgets don't get native desktop activation changes, + // only aura activation changes). + aura::Window* active_window = activation_client->GetActiveWindow(); + if (active_window) + activation_client->DeactivateWindow(active_window); + } +} + //////////////////////////////////////////////////////////////////////////////// // DesktopNativeWidgetAura, internal::NativeWidgetPrivate implementation: @@ -225,7 +274,14 @@ void DesktopNativeWidgetAura::InitNativeWidget( const Widget::InitParams& params) { ownership_ = params.ownership; - window_->set_user_data(this); + NativeWidgetAura::RegisterNativeWidgetForWindow(this, window_); + // Animations on TYPE_WINDOW are handled by the OS. Additionally if we animate + // these windows the size of the window gets augmented, effecting restore + // bounds and maximized windows in bad ways. + if (params.type == Widget::InitParams::TYPE_WINDOW && + !params.remove_standard_frame) { + window_->SetProperty(aura::client::kAnimationsDisabledKey, true); + } window_->SetType(GetAuraWindowTypeForWidgetType(params.type)); window_->SetTransparent(true); window_->Init(params.layer_type); @@ -240,6 +296,14 @@ void DesktopNativeWidgetAura::InitNativeWidget( this, params.bounds); root_window_.reset( desktop_root_window_host_->Init(window_, params)); + + content_window_container_ = new aura::Window(NULL); + content_window_container_->Init(ui::LAYER_NOT_DRAWN); + content_window_container_->Show(); + content_window_container_->AddChild(window_); + content_window_container_->SetBounds(root_window_->bounds()); + root_window_->AddChild(content_window_container_); + root_window_->AddRootWindowObserver(this); stacking_client_.reset( @@ -249,11 +313,8 @@ void DesktopNativeWidgetAura::InitNativeWidget( aura::client::SetDragDropDelegate(window_, this); tooltip_manager_.reset(new views::TooltipManagerAura(window_, GetWidget())); - tooltip_controller_.reset( - new corewm::TooltipController(gfx::SCREEN_TYPE_NATIVE)); - aura::client::SetTooltipClient(root_window_.get(), - tooltip_controller_.get()); - root_window_->AddPreTargetHandler(tooltip_controller_.get()); + + scoped_tooltip_client_.reset(new ScopedTooltipClient(root_window_.get())); if (params.opacity == Widget::InitParams::TRANSLUCENT_WINDOW) { visibility_controller_.reset(new views::corewm::VisibilityController); @@ -315,15 +376,16 @@ Widget* DesktopNativeWidgetAura::GetTopLevelWidget() { } const ui::Compositor* DesktopNativeWidgetAura::GetCompositor() const { - return window_->layer()->GetCompositor(); + return window_ ? window_->layer()->GetCompositor() : NULL; } ui::Compositor* DesktopNativeWidgetAura::GetCompositor() { - return window_->layer()->GetCompositor(); + return const_cast<ui::Compositor*>( + const_cast<const DesktopNativeWidgetAura*>(this)->GetCompositor()); } ui::Layer* DesktopNativeWidgetAura::GetLayer() { - return window_->layer(); + return window_ ? window_->layer() : NULL; } void DesktopNativeWidgetAura::ReorderNativeViews() { @@ -335,11 +397,12 @@ void DesktopNativeWidgetAura::ViewRemoved(View* view) { void DesktopNativeWidgetAura::SetNativeWindowProperty(const char* name, void* value) { - window_->SetNativeWindowProperty(name, value); + if (window_) + window_->SetNativeWindowProperty(name, value); } void* DesktopNativeWidgetAura::GetNativeWindowProperty(const char* name) const { - return window_->GetNativeWindowProperty(name); + return window_ ? window_->GetNativeWindowProperty(name) : NULL; } TooltipManager* DesktopNativeWidgetAura::GetTooltipManager() const { @@ -347,6 +410,9 @@ TooltipManager* DesktopNativeWidgetAura::GetTooltipManager() const { } void DesktopNativeWidgetAura::SetCapture() { + if (!window_) + return; + window_->SetCapture(); // aura::Window doesn't implicitly update capture on the RootWindowHost, so // we have to do that manually. @@ -355,6 +421,9 @@ void DesktopNativeWidgetAura::SetCapture() { } void DesktopNativeWidgetAura::ReleaseCapture() { + if (!window_) + return; + window_->ReleaseCapture(); // aura::Window doesn't implicitly update capture on the RootWindowHost, so // we have to do that manually. @@ -363,7 +432,8 @@ void DesktopNativeWidgetAura::ReleaseCapture() { } bool DesktopNativeWidgetAura::HasCapture() const { - return window_->HasCapture() && desktop_root_window_host_->HasCapture(); + return window_ && window_->HasCapture() && + desktop_root_window_host_->HasCapture(); } InputMethod* DesktopNativeWidgetAura::CreateInputMethod() { @@ -377,46 +447,53 @@ internal::InputMethodDelegate* } void DesktopNativeWidgetAura::CenterWindow(const gfx::Size& size) { - desktop_root_window_host_->CenterWindow(size); + if (window_) + desktop_root_window_host_->CenterWindow(size); } void DesktopNativeWidgetAura::GetWindowPlacement( gfx::Rect* bounds, ui::WindowShowState* maximized) const { - desktop_root_window_host_->GetWindowPlacement(bounds, maximized); + if (window_) + desktop_root_window_host_->GetWindowPlacement(bounds, maximized); } void DesktopNativeWidgetAura::SetWindowTitle(const string16& title) { - desktop_root_window_host_->SetWindowTitle(title); + if (window_) + desktop_root_window_host_->SetWindowTitle(title); } void DesktopNativeWidgetAura::SetWindowIcons(const gfx::ImageSkia& window_icon, const gfx::ImageSkia& app_icon) { - desktop_root_window_host_->SetWindowIcons(window_icon, app_icon); + if (window_) + desktop_root_window_host_->SetWindowIcons(window_icon, app_icon); } void DesktopNativeWidgetAura::InitModalType(ui::ModalType modal_type) { // 99% of the time, we should not be asked to create a - // DesktopNativeWidgetAura that is modal. The case where this breaks down is - // when there are no browser windows and a background extension tries to - // display a simple alert dialog. (This case was masked because we used to - // have a hidden RootWindow which was the parent of these modal dialogs; they - // weren't displayed to the user.) + // DesktopNativeWidgetAura that is modal. We only support window modal + // dialogs on the same lines as non AURA. + desktop_root_window_host_->InitModalType(modal_type); } gfx::Rect DesktopNativeWidgetAura::GetWindowBoundsInScreen() const { - return desktop_root_window_host_->GetWindowBoundsInScreen(); + return window_ ? desktop_root_window_host_->GetWindowBoundsInScreen() : + gfx::Rect(); } gfx::Rect DesktopNativeWidgetAura::GetClientAreaBoundsInScreen() const { - return desktop_root_window_host_->GetClientAreaBoundsInScreen(); + return window_ ? desktop_root_window_host_->GetClientAreaBoundsInScreen() : + gfx::Rect(); } gfx::Rect DesktopNativeWidgetAura::GetRestoredBounds() const { - return desktop_root_window_host_->GetRestoredBounds(); + return window_ ? desktop_root_window_host_->GetRestoredBounds() : gfx::Rect(); } void DesktopNativeWidgetAura::SetBounds(const gfx::Rect& bounds) { + if (!window_) + return; + float scale = 1; aura::RootWindow* root = root_window_.get(); if (root) { @@ -427,10 +504,15 @@ void DesktopNativeWidgetAura::SetBounds(const gfx::Rect& bounds) { gfx::ToCeiledPoint(gfx::ScalePoint(bounds.origin(), scale)), gfx::ToFlooredSize(gfx::ScaleSize(bounds.size(), scale))); desktop_root_window_host_->AsRootWindowHost()->SetBounds(bounds_in_pixels); + if (content_window_container_) { + content_window_container_->SetBounds( + content_window_container_->GetRootWindow()->bounds()); + } } void DesktopNativeWidgetAura::SetSize(const gfx::Size& size) { - desktop_root_window_host_->SetSize(size); + if (window_) + desktop_root_window_host_->SetSize(size); } void DesktopNativeWidgetAura::StackAbove(gfx::NativeView native_view) { @@ -443,98 +525,117 @@ void DesktopNativeWidgetAura::StackBelow(gfx::NativeView native_view) { } void DesktopNativeWidgetAura::SetShape(gfx::NativeRegion shape) { - desktop_root_window_host_->SetShape(shape); + if (window_) + desktop_root_window_host_->SetShape(shape); } void DesktopNativeWidgetAura::Close() { + if (!window_) + return; desktop_root_window_host_->Close(); - if (window_) - window_->SuppressPaint(); + window_->SuppressPaint(); } void DesktopNativeWidgetAura::CloseNow() { - desktop_root_window_host_->CloseNow(); + if (window_) + desktop_root_window_host_->CloseNow(); } void DesktopNativeWidgetAura::Show() { + if (!window_) + return; desktop_root_window_host_->AsRootWindowHost()->Show(); window_->Show(); } void DesktopNativeWidgetAura::Hide() { + if (!window_) + return; desktop_root_window_host_->AsRootWindowHost()->Hide(); - if (window_) - window_->Hide(); + window_->Hide(); } void DesktopNativeWidgetAura::ShowMaximizedWithBounds( const gfx::Rect& restored_bounds) { + if (!window_) + return; desktop_root_window_host_->ShowMaximizedWithBounds(restored_bounds); window_->Show(); } void DesktopNativeWidgetAura::ShowWithWindowState(ui::WindowShowState state) { + if (!window_) + return; desktop_root_window_host_->ShowWindowWithState(state); window_->Show(); } bool DesktopNativeWidgetAura::IsVisible() const { - return desktop_root_window_host_->IsVisible(); + return window_ && desktop_root_window_host_->IsVisible(); } void DesktopNativeWidgetAura::Activate() { - desktop_root_window_host_->Activate(); + if (window_) + desktop_root_window_host_->Activate(); } void DesktopNativeWidgetAura::Deactivate() { - desktop_root_window_host_->Deactivate(); + if (window_) + desktop_root_window_host_->Deactivate(); } bool DesktopNativeWidgetAura::IsActive() const { - return desktop_root_window_host_->IsActive(); + return window_ && desktop_root_window_host_->IsActive(); } void DesktopNativeWidgetAura::SetAlwaysOnTop(bool always_on_top) { - desktop_root_window_host_->SetAlwaysOnTop(always_on_top); + if (window_) + desktop_root_window_host_->SetAlwaysOnTop(always_on_top); } void DesktopNativeWidgetAura::Maximize() { - desktop_root_window_host_->Maximize(); + if (window_) + desktop_root_window_host_->Maximize(); } void DesktopNativeWidgetAura::Minimize() { - desktop_root_window_host_->Minimize(); + if (window_) + desktop_root_window_host_->Minimize(); } bool DesktopNativeWidgetAura::IsMaximized() const { - return desktop_root_window_host_->IsMaximized(); + return window_ && desktop_root_window_host_->IsMaximized(); } bool DesktopNativeWidgetAura::IsMinimized() const { - return desktop_root_window_host_->IsMinimized(); + return window_ && desktop_root_window_host_->IsMinimized(); } void DesktopNativeWidgetAura::Restore() { - desktop_root_window_host_->Restore(); + if (window_) + desktop_root_window_host_->Restore(); } void DesktopNativeWidgetAura::SetFullscreen(bool fullscreen) { - desktop_root_window_host_->SetFullscreen(fullscreen); + if (window_) + desktop_root_window_host_->SetFullscreen(fullscreen); } bool DesktopNativeWidgetAura::IsFullscreen() const { - return desktop_root_window_host_->IsFullscreen(); + return window_ && desktop_root_window_host_->IsFullscreen(); } void DesktopNativeWidgetAura::SetOpacity(unsigned char opacity) { - desktop_root_window_host_->SetOpacity(opacity); + if (window_) + desktop_root_window_host_->SetOpacity(opacity); } void DesktopNativeWidgetAura::SetUseDragFrame(bool use_drag_frame) { } void DesktopNativeWidgetAura::FlashFrame(bool flash_frame) { - desktop_root_window_host_->FlashFrame(flash_frame); + if (window_) + desktop_root_window_host_->FlashFrame(flash_frame); } void DesktopNativeWidgetAura::RunShellDrag( @@ -560,6 +661,8 @@ void DesktopNativeWidgetAura::SetCursor(gfx::NativeCursor cursor) { } bool DesktopNativeWidgetAura::IsMouseEventsEnabled() const { + if (!window_) + return false; aura::client::CursorClient* cursor_client = aura::client::GetCursorClient(window_->GetRootWindow()); return cursor_client ? cursor_client->IsMouseEventsEnabled() : true; @@ -579,34 +682,45 @@ gfx::Rect DesktopNativeWidgetAura::GetWorkAreaBoundsInScreen() const { } void DesktopNativeWidgetAura::SetInactiveRenderingDisabled(bool value) { + if (!window_) + return; + if (!value) { active_window_observer_.reset(); } else { active_window_observer_.reset( new NativeWidgetAuraWindowObserver(window_, native_widget_delegate_)); } - desktop_root_window_host_->SetInactiveRenderingDisabled(value); } Widget::MoveLoopResult DesktopNativeWidgetAura::RunMoveLoop( const gfx::Vector2d& drag_offset, Widget::MoveLoopSource source) { + if (!window_) + return Widget::MOVE_LOOP_CANCELED; return desktop_root_window_host_->RunMoveLoop(drag_offset, source); } void DesktopNativeWidgetAura::EndMoveLoop() { - desktop_root_window_host_->EndMoveLoop(); + if (window_) + desktop_root_window_host_->EndMoveLoop(); } void DesktopNativeWidgetAura::SetVisibilityChangedAnimationsEnabled( bool value) { - desktop_root_window_host_->SetVisibilityChangedAnimationsEnabled(value); + if (window_) + desktop_root_window_host_->SetVisibilityChangedAnimationsEnabled(value); } ui::NativeTheme* DesktopNativeWidgetAura::GetNativeTheme() const { return DesktopRootWindowHost::GetNativeTheme(window_); } +void DesktopNativeWidgetAura::OnRootViewLayout() const { + if (window_) + desktop_root_window_host_->OnRootViewLayout(); +} + //////////////////////////////////////////////////////////////////////////////// // DesktopNativeWidgetAura, aura::WindowDelegate implementation: @@ -624,6 +738,10 @@ void DesktopNativeWidgetAura::OnBoundsChanged(const gfx::Rect& old_bounds, native_widget_delegate_->OnNativeWidgetMove(); if (old_bounds.size() != new_bounds.size()) native_widget_delegate_->OnNativeWidgetSizeChanged(new_bounds.size()); + if (content_window_container_) { + content_window_container_->SetBounds( + content_window_container_->GetRootWindow()->bounds()); + } } gfx::NativeCursor DesktopNativeWidgetAura::GetCursor(const gfx::Point& point) { @@ -665,11 +783,7 @@ void DesktopNativeWidgetAura::OnWindowDestroying() { shadow_controller_.reset(); // The DesktopRootWindowHost implementation sends OnNativeWidgetDestroying(). tooltip_manager_.reset(); - if (tooltip_controller_.get()) { - root_window_->RemovePreTargetHandler(tooltip_controller_.get()); - tooltip_controller_.reset(); - aura::client::SetTooltipClient(root_window_.get(), NULL); - } + scoped_tooltip_client_.reset(); if (window_modality_controller_) { root_window_->RemovePreTargetHandler(window_modality_controller_.get()); window_modality_controller_.reset(); @@ -694,12 +808,8 @@ void DesktopNativeWidgetAura::GetHitTestMask(gfx::Path* mask) const { native_widget_delegate_->GetHitTestMask(mask); } -scoped_refptr<ui::Texture> DesktopNativeWidgetAura::CopyTexture() { - // The layer we create doesn't have an external texture, so this should never - // get invoked. - NOTREACHED(); - return scoped_refptr<ui::Texture>(); -} +void DesktopNativeWidgetAura::DidRecreateLayer(ui::Layer* old_layer, + ui::Layer* new_layer) {} //////////////////////////////////////////////////////////////////////////////// // DesktopNativeWidgetAura, ui::EventHandler implementation: @@ -780,28 +890,10 @@ void DesktopNativeWidgetAura::OnWindowActivated(aura::Window* gained_active, restore_focus_on_activate_ = false; GetWidget()->GetFocusManager()->RestoreFocusedView(); } else if (lost_active == window_ && GetWidget()->HasFocusManager()) { - bool store_focused_view = corewm::UseFocusControllerOnDesktop(); - if (!store_focused_view) { - // If we're losing focus to a window that is a top level (such as a - // bubble) store the focus. Such a window shares the same - // RootWindowHost, so that such a change won't trigger an activation - // change (which calls StoreFocusedView()). Without this the focused - // view is never told it lost focus. - aura::Window* focused_window = - aura::client::GetFocusClient(window_)->GetFocusedWindow(); - if (focused_window && focused_window != window_) { - Widget* focused_widget = - Widget::GetWidgetForNativeWindow(focused_window); - store_focused_view = focused_widget && focused_widget != GetWidget() && - focused_widget->is_top_level(); - } - } - if (store_focused_view) { - DCHECK(!restore_focus_on_activate_); - restore_focus_on_activate_ = true; - // Pass in false so that ClearNativeFocus() isn't invoked. - GetWidget()->GetFocusManager()->StoreFocusedView(false); - } + DCHECK(!restore_focus_on_activate_); + restore_focus_on_activate_ = true; + // Pass in false so that ClearNativeFocus() isn't invoked. + GetWidget()->GetFocusManager()->StoreFocusedView(false); } } diff --git a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h index b98e1ccc7f9..a70e767ebde 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h +++ b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h @@ -12,6 +12,7 @@ #include "ui/aura/client/focus_change_observer.h" #include "ui/aura/root_window_observer.h" #include "ui/aura/window_delegate.h" +#include "ui/base/cursor/cursor.h" #include "ui/views/ime/input_method_delegate.h" #include "ui/views/widget/native_widget_private.h" @@ -27,8 +28,8 @@ namespace views { namespace corewm { class CompoundEventFilter; class InputMethodEventFilter; +class ScopedCaptureClient; class ShadowController; -class TooltipController; class VisibilityController; class WindowModalityController; } @@ -36,6 +37,7 @@ class WindowModalityController; class DesktopRootWindowHost; class DropHelper; class NativeWidgetAuraWindowObserver; +class ScopedTooltipClient; class TooltipManagerAura; class WindowReorderer; @@ -69,9 +71,16 @@ class VIEWS_EXPORT DesktopNativeWidgetAura return root_window_event_filter_; } + // Invoked from DesktopRootWindowHost creation to create the CaptureClient. + void CreateCaptureClient(aura::RootWindow* root); + // Overridden from NativeWidget: virtual ui::EventHandler* GetEventHandler() OVERRIDE; + // Ensures that the correct window is activated/deactivated based on whether + // we are being activated/deactivated. + void HandleActivationChanged(bool active); + protected: // Overridden from internal::NativeWidgetPrivate: virtual void InitNativeWidget(const Widget::InitParams& params) OVERRIDE; @@ -152,6 +161,7 @@ class VIEWS_EXPORT DesktopNativeWidgetAura virtual void EndMoveLoop() OVERRIDE; virtual void SetVisibilityChangedAnimationsEnabled(bool value) OVERRIDE; virtual ui::NativeTheme* GetNativeTheme() const OVERRIDE; + virtual void OnRootViewLayout() const OVERRIDE; // Overridden from aura::WindowDelegate: virtual gfx::Size GetMinimumSize() const OVERRIDE; @@ -172,7 +182,8 @@ class VIEWS_EXPORT DesktopNativeWidgetAura virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE; virtual bool HasHitTestMask() const OVERRIDE; virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE; - virtual scoped_refptr<ui::Texture> CopyTexture() OVERRIDE; + virtual void DidRecreateLayer(ui::Layer* old_layer, + ui::Layer* new_layer) OVERRIDE; // Overridden from ui::EventHandler: virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; @@ -209,6 +220,8 @@ class VIEWS_EXPORT DesktopNativeWidgetAura // See class documentation for Widget in widget.h for a note about ownership. Widget::InitParams::Ownership ownership_; + scoped_ptr<corewm::ScopedCaptureClient> capture_client_; + // The NativeWidget owns the RootWindow. Required because the RootWindow owns // its RootWindowHost, so DesktopRootWindowHost can't own it. scoped_ptr<aura::RootWindow> root_window_; @@ -224,7 +237,16 @@ class VIEWS_EXPORT DesktopNativeWidgetAura // Ownership passed to RootWindow on Init. DesktopRootWindowHost* desktop_root_window_host_; + + // The content of |root_window_|. WARNING: this may be NULL if deleted out + // from under us. aura::Window* window_; + + // Contains the content window defined above. Ensures that ZOrder changes + // occurring in the content window hierarchy don't affect the other children + // of the root window. + aura::Window* content_window_container_; + internal::NativeWidgetDelegate* native_widget_delegate_; scoped_ptr<aura::client::StackingClient> stacking_client_; @@ -237,7 +259,7 @@ class VIEWS_EXPORT DesktopNativeWidgetAura scoped_ptr<DropHelper> drop_helper_; int last_drop_operation_; - scoped_ptr<corewm::TooltipController> tooltip_controller_; + scoped_ptr<ScopedTooltipClient> scoped_tooltip_client_; scoped_ptr<TooltipManagerAura> tooltip_manager_; scoped_ptr<views::corewm::VisibilityController> visibility_controller_; diff --git a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc new file mode 100644 index 00000000000..1342abaa310 --- /dev/null +++ b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc @@ -0,0 +1,27 @@ +// 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 "ui/aura/window.h" +#include "ui/views/test/views_test_base.h" +#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" +#include "ui/views/widget/widget.h" + +namespace views { + +typedef ViewsTestBase DesktopNativeWidgetAuraTest; + +// Verifies creating a Widget with a parent that is not in a RootWindow doesn't +// crash. +TEST_F(DesktopNativeWidgetAuraTest, CreateWithParentNotInRootWindow) { + scoped_ptr<aura::Window> window(new aura::Window(NULL)); + Widget widget; + Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); + params.bounds = gfx::Rect(0, 0, 200, 200); + params.parent = window.get(); + params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + params.native_widget = new DesktopNativeWidgetAura(&widget); + widget.Init(params); +} + +} // namespace views diff --git a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host.h b/chromium/ui/views/widget/desktop_aura/desktop_root_window_host.h index afc412aad65..583b0ac5773 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host.h +++ b/chromium/ui/views/widget/desktop_aura/desktop_root_window_host.h @@ -109,13 +109,12 @@ class VIEWS_EXPORT DesktopRootWindowHost { virtual void FlashFrame(bool flash_frame) = 0; + virtual void OnRootViewLayout() const = 0; + // Called when the DesktopNativeWidgetAura's aura::Window is focused and // blurred. virtual void OnNativeWidgetFocus() = 0; virtual void OnNativeWidgetBlur() = 0; - - // Paints the host window as activated depending on the bool passed in. - virtual void SetInactiveRenderingDisabled(bool disable_inactive) = 0; }; } // namespace views diff --git a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_ozone.cc b/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_ozone.cc new file mode 100644 index 00000000000..ff905a3e583 --- /dev/null +++ b/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_ozone.cc @@ -0,0 +1,22 @@ +// 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 "ui/aura/root_window_host.h" +#include "ui/views/widget/desktop_aura/desktop_root_window_host.h" +#include "ui/views/widget/desktop_aura/desktop_factory_ozone.h" + +namespace views { + +DesktopRootWindowHost* DesktopRootWindowHost::Create( + internal::NativeWidgetDelegate* native_widget_delegate, + DesktopNativeWidgetAura* desktop_native_widget_aura, + const gfx::Rect& initial_bounds) { + DesktopFactoryOzone* d_factory = DesktopFactoryOzone::GetInstance(); + + return d_factory->CreateRootWindowHost(native_widget_delegate, + desktop_native_widget_aura, + initial_bounds); +} + +} // namespace views diff --git a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc b/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc index 159ffc1080e..ae4a982b19e 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc +++ b/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc @@ -15,11 +15,11 @@ #include "ui/base/cursor/cursor_loader_win.h" #include "ui/base/ime/input_method.h" #include "ui/base/ime/win/tsf_bridge.h" -#include "ui/base/win/dpi.h" #include "ui/base/win/shell.h" #include "ui/gfx/insets.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/path_win.h" +#include "ui/gfx/win/dpi.h" #include "ui/native_theme/native_theme_aura.h" #include "ui/native_theme/native_theme_win.h" #include "ui/views/corewm/compound_event_filter.h" @@ -29,8 +29,6 @@ #include "ui/views/corewm/input_method_event_filter.h" #include "ui/views/corewm/window_animations.h" #include "ui/views/ime/input_method_bridge.h" -#include "ui/views/widget/desktop_aura/desktop_activation_client.h" -#include "ui/views/widget/desktop_aura/desktop_capture_client.h" #include "ui/views/widget/desktop_aura/desktop_cursor_loader_updater.h" #include "ui/views/widget/desktop_aura/desktop_dispatcher_client.h" #include "ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h" @@ -68,10 +66,8 @@ DesktopRootWindowHostWin::DesktopRootWindowHostWin( } DesktopRootWindowHostWin::~DesktopRootWindowHostWin() { - if (corewm::UseFocusControllerOnDesktop()) { - aura::client::SetFocusClient(root_window_, NULL); - aura::client::SetActivationClient(root_window_, NULL); - } + aura::client::SetFocusClient(root_window_, NULL); + aura::client::SetActivationClient(root_window_, NULL); } // static @@ -109,46 +105,32 @@ aura::RootWindow* DesktopRootWindowHostWin::Init( native_widget_delegate_); HWND parent_hwnd = NULL; - aura::Window* parent_window = params.parent; - if (parent_window) - parent_hwnd = parent_window->GetRootWindow()->GetAcceleratedWidget(); + if (params.parent && params.parent->GetRootWindow()) + parent_hwnd = params.parent->GetRootWindow()->GetAcceleratedWidget(); message_handler_->set_remove_standard_frame(params.remove_standard_frame); has_non_client_view_ = Widget::RequiresNonClientView(params.type); - gfx::Rect pixel_bounds = ui::win::DIPToScreenRect(params.bounds); + gfx::Rect pixel_bounds = gfx::win::DIPToScreenRect(params.bounds); message_handler_->Init(parent_hwnd, pixel_bounds); aura::RootWindow::CreateParams rw_params(params.bounds); rw_params.host = this; root_window_ = new aura::RootWindow(rw_params); - // TODO(beng): We probably need to move these two calls to some function that - // can change depending on the native-ness of the frame. For right - // now in the hack-n-slash days of win-aura, we can just - // unilaterally turn this on. - root_window_->compositor()->SetHostHasTransparentBackground(true); - root_window_->SetTransparent(true); - + SetWindowTransparency(); root_window_->Init(); root_window_->AddChild(content_window_); - capture_client_.reset(new views::DesktopCaptureClient(root_window_)); - aura::client::SetCaptureClient(root_window_, capture_client_.get()); + desktop_native_widget_aura_->CreateCaptureClient(root_window_); - if (corewm::UseFocusControllerOnDesktop()) { - corewm::FocusController* focus_controller = - new corewm::FocusController(new DesktopFocusRules); - focus_client_.reset(focus_controller); - aura::client::SetFocusClient(root_window_, focus_controller); - aura::client::SetActivationClient(root_window_, focus_controller); - root_window_->AddPreTargetHandler(focus_controller); - } else { - focus_client_.reset(new aura::FocusManager); - aura::client::SetFocusClient(root_window_, focus_client_.get()); - activation_client_.reset(new DesktopActivationClient(root_window_)); - } + corewm::FocusController* focus_controller = + new corewm::FocusController(new DesktopFocusRules(content_window)); + focus_client_.reset(focus_controller); + aura::client::SetFocusClient(root_window_, focus_controller); + aura::client::SetActivationClient(root_window_, focus_controller); + root_window_->AddPreTargetHandler(focus_controller); dispatcher_client_.reset(new DesktopDispatcherClient); aura::client::SetDispatcherClient(root_window_, @@ -220,7 +202,7 @@ void DesktopRootWindowHostWin::ShowWindowWithState( void DesktopRootWindowHostWin::ShowMaximizedWithBounds( const gfx::Rect& restored_bounds) { - gfx::Rect pixel_bounds = ui::win::DIPToScreenRect(restored_bounds); + gfx::Rect pixel_bounds = gfx::win::DIPToScreenRect(restored_bounds); message_handler_->ShowMaximizedWithBounds(pixel_bounds); } @@ -229,12 +211,12 @@ bool DesktopRootWindowHostWin::IsVisible() const { } void DesktopRootWindowHostWin::SetSize(const gfx::Size& size) { - gfx::Size size_in_pixels = ui::win::DIPToScreenSize(size); + gfx::Size size_in_pixels = gfx::win::DIPToScreenSize(size); message_handler_->SetSize(size_in_pixels); } void DesktopRootWindowHostWin::CenterWindow(const gfx::Size& size) { - gfx::Size size_in_pixels = ui::win::DIPToScreenSize(size); + gfx::Size size_in_pixels = gfx::win::DIPToScreenSize(size); message_handler_->CenterWindow(size_in_pixels); } @@ -242,22 +224,22 @@ void DesktopRootWindowHostWin::GetWindowPlacement( gfx::Rect* bounds, ui::WindowShowState* show_state) const { message_handler_->GetWindowPlacement(bounds, show_state); - *bounds = ui::win::ScreenToDIPRect(*bounds); + *bounds = gfx::win::ScreenToDIPRect(*bounds); } gfx::Rect DesktopRootWindowHostWin::GetWindowBoundsInScreen() const { gfx::Rect pixel_bounds = message_handler_->GetWindowBoundsInScreen(); - return ui::win::ScreenToDIPRect(pixel_bounds); + return gfx::win::ScreenToDIPRect(pixel_bounds); } gfx::Rect DesktopRootWindowHostWin::GetClientAreaBoundsInScreen() const { gfx::Rect pixel_bounds = message_handler_->GetClientAreaBoundsInScreen(); - return ui::win::ScreenToDIPRect(pixel_bounds); + return gfx::win::ScreenToDIPRect(pixel_bounds); } gfx::Rect DesktopRootWindowHostWin::GetRestoredBounds() const { gfx::Rect pixel_bounds = message_handler_->GetRestoredBounds(); - return ui::win::ScreenToDIPRect(pixel_bounds); + return gfx::win::ScreenToDIPRect(pixel_bounds); } gfx::Rect DesktopRootWindowHostWin::GetWorkAreaBoundsInScreen() const { @@ -267,7 +249,7 @@ gfx::Rect DesktopRootWindowHostWin::GetWorkAreaBoundsInScreen() const { MONITOR_DEFAULTTONEAREST), &monitor_info); gfx::Rect pixel_bounds = gfx::Rect(monitor_info.rcWork); - return ui::win::ScreenToDIPRect(pixel_bounds); + return gfx::win::ScreenToDIPRect(pixel_bounds); } void DesktopRootWindowHostWin::SetShape(gfx::NativeRegion native_region) { @@ -347,6 +329,7 @@ bool DesktopRootWindowHostWin::ShouldUseNativeFrame() { void DesktopRootWindowHostWin::FrameTypeChanged() { message_handler_->FrameTypeChanged(); + SetWindowTransparency(); } NonClientFrameView* DesktopRootWindowHostWin::CreateNonClientFrameView() { @@ -356,6 +339,7 @@ NonClientFrameView* DesktopRootWindowHostWin::CreateNonClientFrameView() { void DesktopRootWindowHostWin::SetFullscreen(bool fullscreen) { message_handler_->fullscreen_handler()->SetFullscreen(fullscreen); + SetWindowTransparency(); } bool DesktopRootWindowHostWin::IsFullscreen() const { @@ -381,6 +365,9 @@ void DesktopRootWindowHostWin::FlashFrame(bool flash_frame) { message_handler_->FlashFrame(flash_frame); } +void DesktopRootWindowHostWin::OnRootViewLayout() const { +} + void DesktopRootWindowHostWin::OnNativeWidgetFocus() { // HWNDMessageHandler will perform the proper updating on its own. } @@ -388,13 +375,6 @@ void DesktopRootWindowHostWin::OnNativeWidgetFocus() { void DesktopRootWindowHostWin::OnNativeWidgetBlur() { } -void DesktopRootWindowHostWin::SetInactiveRenderingDisabled( - bool disable_inactive) { - // Force the non-client area (most notably the title bar) to paint as either - // active or inactive, depending on the input. - SendMessage(message_handler_->hwnd(), WM_NCACTIVATE, !!disable_inactive, 0); -} - //////////////////////////////////////////////////////////////////////////////// // DesktopRootWindowHostWin, RootWindowHost implementation: @@ -422,6 +402,7 @@ void DesktopRootWindowHostWin::Hide() { } void DesktopRootWindowHostWin::ToggleFullScreen() { + SetWindowTransparency(); } // GetBounds and SetBounds work in pixel coordinates, whereas other get/set @@ -506,14 +487,6 @@ void DesktopRootWindowHostWin::MoveCursorTo(const gfx::Point& location) { void DesktopRootWindowHostWin::SetFocusWhenShown(bool focus_when_shown) { } -bool DesktopRootWindowHostWin::CopyAreaToSkCanvas( - const gfx::Rect& source_bounds, - const gfx::Point& dest_offset, - SkCanvas* canvas) { - NOTIMPLEMENTED(); - return false; -} - void DesktopRootWindowHostWin::PostNativeEvent( const base::NativeEvent& native_event) { } @@ -610,7 +583,7 @@ bool DesktopRootWindowHostWin::WillProcessWorkAreaChange() const { int DesktopRootWindowHostWin::GetNonClientComponent( const gfx::Point& point) const { - gfx::Point dip_position = ui::win::ScreenToDIPPoint(point); + gfx::Point dip_position = gfx::win::ScreenToDIPPoint(point); return native_widget_delegate_->GetNonClientComponent(dip_position); } @@ -661,20 +634,7 @@ void DesktopRootWindowHostWin::HandleAppDeactivated() { void DesktopRootWindowHostWin::HandleActivationChanged(bool active) { if (active) root_window_host_delegate_->OnHostActivated(); - native_widget_delegate_->OnNativeWidgetActivationChanged(active); - // If we're not active we need to deactivate the corresponding aura::Window. - // This way if a child widget is active it gets correctly deactivated (child - // widgets don't get native desktop activation changes, only aura activation - // changes). - if (!active) { - aura::client::ActivationClient* activation_client = - aura::client::GetActivationClient(root_window_); - if (activation_client) { - aura::Window* active_window = activation_client->GetActiveWindow(); - if (active_window) - activation_client->DeactivateWindow(active_window); - } - } + desktop_native_widget_aura_->HandleActivationChanged(active); } bool DesktopRootWindowHostWin::HandleAppCommand(short command) { @@ -751,6 +711,10 @@ void DesktopRootWindowHostWin::HandleWorkAreaChanged() { GetWidget()->widget_delegate()->OnWorkAreaChanged(); } +void DesktopRootWindowHostWin::HandleVisibilityChanging(bool visible) { + native_widget_delegate_->OnNativeWidgetVisibilityChanging(visible); +} + void DesktopRootWindowHostWin::HandleVisibilityChanged(bool visible) { native_widget_delegate_->OnNativeWidgetVisibilityChanged(visible); } @@ -762,7 +726,7 @@ void DesktopRootWindowHostWin::HandleClientSizeChanged( if (root_window_host_delegate_) root_window_host_delegate_->OnHostResized(new_size); // TODO(beng): replace with a layout manager?? - gfx::Size dip_size = ui::win::ScreenToDIPSize(without_expansion); + gfx::Size dip_size = gfx::win::ScreenToDIPSize(without_expansion); content_window_->SetBounds(gfx::Rect(dip_size)); native_widget_delegate_->OnNativeWidgetSizeChanged(dip_size); } @@ -804,9 +768,14 @@ bool DesktopRootWindowHostWin::HandleUntranslatedKeyEvent( OnHostKeyEvent(duplicate_event.get()); } -bool DesktopRootWindowHostWin::HandleTouchEvent( +void DesktopRootWindowHostWin::HandleTouchEvent( const ui::TouchEvent& event) { - return root_window_host_delegate_->OnHostTouchEvent( + // HWNDMessageHandler asynchronously processes touch events. Because of this + // it's possible for the aura::RootWindow to have been destroyed by the time + // we attempt to process them. + if (!GetWidget()->GetNativeView()) + return; + root_window_host_delegate_->OnHostTouchEvent( const_cast<ui::TouchEvent*>(&event)); } @@ -877,6 +846,12 @@ HWND DesktopRootWindowHostWin::GetHWND() const { return message_handler_->hwnd(); } +void DesktopRootWindowHostWin::SetWindowTransparency() { + bool transparent = ShouldUseNativeFrame() && !IsFullscreen(); + root_window_->compositor()->SetHostHasTransparentBackground(transparent); + root_window_->SetTransparent(transparent); +} + //////////////////////////////////////////////////////////////////////////////// // DesktopRootWindowHost, public: diff --git a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_win.h b/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_win.h index 9ad6b6998c9..3e112087f00 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_win.h +++ b/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_win.h @@ -19,8 +19,6 @@ class ScreenPositionClient; } namespace views { -class DesktopActivationClient; -class DesktopCaptureClient; class DesktopCursorClient; class DesktopDispatcherClient; class DesktopDragDropClientWin; @@ -94,9 +92,9 @@ class VIEWS_EXPORT DesktopRootWindowHostWin const gfx::ImageSkia& app_icon) OVERRIDE; virtual void InitModalType(ui::ModalType modal_type) OVERRIDE; virtual void FlashFrame(bool flash_frame) OVERRIDE; + virtual void OnRootViewLayout() const OVERRIDE; virtual void OnNativeWidgetFocus() OVERRIDE; virtual void OnNativeWidgetBlur() OVERRIDE; - virtual void SetInactiveRenderingDisabled(bool disable_inactive) OVERRIDE; // Overridden from aura::RootWindowHost: virtual void SetDelegate(aura::RootWindowHostDelegate* delegate) OVERRIDE; @@ -119,9 +117,6 @@ class VIEWS_EXPORT DesktopRootWindowHostWin virtual void OnCursorVisibilityChanged(bool show) OVERRIDE; virtual void MoveCursorTo(const gfx::Point& location) OVERRIDE; virtual void SetFocusWhenShown(bool focus_when_shown) OVERRIDE; - virtual bool CopyAreaToSkCanvas(const gfx::Rect& source_bounds, - const gfx::Point& dest_offset, - SkCanvas* canvas) OVERRIDE; virtual void PostNativeEvent(const base::NativeEvent& native_event) OVERRIDE; virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE; virtual void PrepareForShutdown() OVERRIDE; @@ -175,6 +170,7 @@ class VIEWS_EXPORT DesktopRootWindowHostWin virtual void HandleEndWMSizeMove() OVERRIDE; virtual void HandleMove() OVERRIDE; virtual void HandleWorkAreaChanged() OVERRIDE; + virtual void HandleVisibilityChanging(bool visible) OVERRIDE; virtual void HandleVisibilityChanged(bool visible) OVERRIDE; virtual void HandleClientSizeChanged(const gfx::Size& new_size) OVERRIDE; virtual void HandleFrameChanged() OVERRIDE; @@ -183,7 +179,7 @@ class VIEWS_EXPORT DesktopRootWindowHostWin virtual bool HandleMouseEvent(const ui::MouseEvent& event) OVERRIDE; virtual bool HandleKeyEvent(const ui::KeyEvent& event) OVERRIDE; virtual bool HandleUntranslatedKeyEvent(const ui::KeyEvent& event) OVERRIDE; - virtual bool HandleTouchEvent(const ui::TouchEvent& event) OVERRIDE; + virtual void HandleTouchEvent(const ui::TouchEvent& event) OVERRIDE; virtual bool HandleIMEMessage(UINT message, WPARAM w_param, LPARAM l_param, @@ -211,15 +207,14 @@ class VIEWS_EXPORT DesktopRootWindowHostWin HWND GetHWND() const; private: + void SetWindowTransparency(); + // We are owned by the RootWindow, but we have to have a back pointer to it. aura::RootWindow* root_window_; scoped_ptr<HWNDMessageHandler> message_handler_; - scoped_ptr<DesktopCaptureClient> capture_client_; scoped_ptr<DesktopDispatcherClient> dispatcher_client_; scoped_ptr<aura::client::FocusClient> focus_client_; - // Depends on focus_manager_. - scoped_ptr<DesktopActivationClient> activation_client_; // TODO(beng): Consider providing an interface to DesktopNativeWidgetAura // instead of providing this route back to Widget. diff --git a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_x11.cc b/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_x11.cc index 8c4ba7c8da5..1610558b3cb 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_x11.cc +++ b/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_x11.cc @@ -10,7 +10,7 @@ #include <X11/Xregion.h> #include <X11/Xutil.h> -#include "base/message_loop/message_pump_aurax11.h" +#include "base/message_loop/message_pump_x11.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "third_party/skia/include/core/SkPath.h" @@ -20,20 +20,18 @@ #include "ui/aura/root_window.h" #include "ui/aura/window_property.h" #include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h" -#include "ui/base/events/event_utils.h" #include "ui/base/touch/touch_factory_x11.h" #include "ui/base/x/x11_util.h" +#include "ui/events/event_utils.h" #include "ui/gfx/insets.h" #include "ui/gfx/path_x11.h" -#include "ui/linux_ui/linux_ui.h" #include "ui/native_theme/native_theme.h" #include "ui/views/corewm/compound_event_filter.h" #include "ui/views/corewm/corewm_switches.h" #include "ui/views/corewm/cursor_manager.h" #include "ui/views/corewm/focus_controller.h" #include "ui/views/ime/input_method.h" -#include "ui/views/widget/desktop_aura/desktop_activation_client.h" -#include "ui/views/widget/desktop_aura/desktop_capture_client.h" +#include "ui/views/linux_ui/linux_ui.h" #include "ui/views/widget/desktop_aura/desktop_cursor_loader_updater_aurax11.h" #include "ui/views/widget/desktop_aura/desktop_dispatcher_client.h" #include "ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h" @@ -116,12 +114,13 @@ DesktopRootWindowHostX11::DesktopRootWindowHostX11( DesktopNativeWidgetAura* desktop_native_widget_aura, const gfx::Rect& initial_bounds) : close_widget_factory_(this), - xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()), + xdisplay_(gfx::GetXDisplay()), xwindow_(0), x_root_window_(DefaultRootWindow(xdisplay_)), atom_cache_(xdisplay_, kAtomsToCache), window_mapped_(false), focus_when_shown_(false), + is_fullscreen_(false), current_cursor_(ui::kCursorNull), native_widget_delegate_(native_widget_delegate), desktop_native_widget_aura_(desktop_native_widget_aura) { @@ -129,10 +128,8 @@ DesktopRootWindowHostX11::DesktopRootWindowHostX11( DesktopRootWindowHostX11::~DesktopRootWindowHostX11() { root_window_->ClearProperty(kHostForRootWindow); - if (corewm::UseFocusControllerOnDesktop()) { - aura::client::SetFocusClient(root_window_, NULL); - aura::client::SetActivationClient(root_window_, NULL); - } + aura::client::SetFocusClient(root_window_, NULL); + aura::client::SetActivationClient(root_window_, NULL); } // static @@ -161,20 +158,8 @@ void DesktopRootWindowHostX11::HandleNativeWidgetActivationChanged( bool active) { if (active) root_window_host_delegate_->OnHostActivated(); - native_widget_delegate_->OnNativeWidgetActivationChanged(active); - // If we're not active we need to deactivate the corresponding aura::Window. - // This way if a child widget is active it gets correctly deactivated (child - // widgets don't get native desktop activation changes, only aura activation - // changes). - if (!active) { - aura::client::ActivationClient* activation_client = - aura::client::GetActivationClient(root_window_); - if (activation_client) { - aura::Window* active_window = activation_client->GetActiveWindow(); - if (active_window) - activation_client->DeactivateWindow(active_window); - } - } + + desktop_native_widget_aura_->HandleActivationChanged(active); native_widget_delegate_->AsWidget()->GetRootView()->SchedulePaint(); } @@ -248,7 +233,7 @@ void DesktopRootWindowHostX11::CloseNow() { open_windows().remove(xwindow_); // Actually free our native resources. - base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_); + base::MessagePumpX11::Current()->RemoveDispatcherForWindow(xwindow_); XDestroyWindow(xdisplay_, xwindow_); xwindow_ = None; @@ -317,9 +302,17 @@ void DesktopRootWindowHostX11::GetWindowPlacement( ui::WindowShowState* show_state) const { *bounds = bounds_; - // TODO(erg): This needs a better implementation. For now, we're just pass - // back the normal state until we keep track of this. - *show_state = ui::SHOW_STATE_NORMAL; + if (IsFullscreen()) { + *show_state = ui::SHOW_STATE_FULLSCREEN; + } else if (IsMinimized()) { + *show_state = ui::SHOW_STATE_MINIMIZED; + } else if (IsMaximized()) { + *show_state = ui::SHOW_STATE_MAXIMIZED; + } else if (!IsActive()) { + *show_state = ui::SHOW_STATE_INACTIVE; + } else { + *show_state = ui::SHOW_STATE_NORMAL; + } } gfx::Rect DesktopRootWindowHostX11::GetWindowBoundsInScreen() const { @@ -488,13 +481,14 @@ NonClientFrameView* DesktopRootWindowHostX11::CreateNonClientFrameView() { } void DesktopRootWindowHostX11::SetFullscreen(bool fullscreen) { + is_fullscreen_ = fullscreen; SetWMSpecState(fullscreen, atom_cache_.GetAtom("_NET_WM_STATE_FULLSCREEN"), None); } bool DesktopRootWindowHostX11::IsFullscreen() const { - return HasWMSpecProperty("_NET_WM_STATE_FULLSCREEN"); + return is_fullscreen_; } void DesktopRootWindowHostX11::SetOpacity(unsigned char opacity) { @@ -521,8 +515,15 @@ void DesktopRootWindowHostX11::SetWindowIcons( } void DesktopRootWindowHostX11::InitModalType(ui::ModalType modal_type) { - // TODO(erg): - NOTIMPLEMENTED(); + switch (modal_type) { + case ui::MODAL_TYPE_NONE: + break; + default: + // TODO(erg): Figure out under what situations |modal_type| isn't + // none. The comment in desktop_native_widget_aura.cc suggests that this + // is rare. + NOTIMPLEMENTED(); + } } void DesktopRootWindowHostX11::FlashFrame(bool flash_frame) { @@ -530,6 +531,35 @@ void DesktopRootWindowHostX11::FlashFrame(bool flash_frame) { NOTIMPLEMENTED(); } +void DesktopRootWindowHostX11::OnRootViewLayout() const { + if (!window_mapped_) + return; + + XSizeHints hints; + long supplied_return; + XGetWMNormalHints(xdisplay_, xwindow_, &hints, &supplied_return); + + gfx::Size minimum = native_widget_delegate_->GetMinimumSize(); + if (minimum.IsEmpty()) { + hints.flags &= ~PMinSize; + } else { + hints.flags |= PMinSize; + hints.min_width = minimum.width(); + hints.min_height = minimum.height(); + } + + gfx::Size maximum = native_widget_delegate_->GetMaximumSize(); + if (maximum.IsEmpty()) { + hints.flags &= ~PMaxSize; + } else { + hints.flags |= PMaxSize; + hints.max_width = maximum.width(); + hints.max_height = maximum.height(); + } + + XSetWMNormalHints(xdisplay_, xwindow_, &hints); +} + void DesktopRootWindowHostX11::OnNativeWidgetFocus() { native_widget_delegate_->AsWidget()->GetInputMethod()->OnFocus(); } @@ -539,10 +569,6 @@ void DesktopRootWindowHostX11::OnNativeWidgetBlur() { native_widget_delegate_->AsWidget()->GetInputMethod()->OnBlur(); } -void DesktopRootWindowHostX11::SetInactiveRenderingDisabled( - bool disable_inactive) { -} - //////////////////////////////////////////////////////////////////////////////// // DesktopRootWindowHostX11, aura::RootWindowHost implementation: @@ -574,7 +600,7 @@ void DesktopRootWindowHostX11::Show() { // We now block until our window is mapped. Some X11 APIs will crash and // burn if passed |xwindow_| before the window is mapped, and XMapWindow is // asynchronous. - base::MessagePumpAuraX11::Current()->BlockUntilWindowMapped(xwindow_); + base::MessagePumpX11::Current()->BlockUntilWindowMapped(xwindow_); window_mapped_ = true; } } @@ -731,14 +757,6 @@ void DesktopRootWindowHostX11::SetFocusWhenShown(bool focus_when_shown) { } } -bool DesktopRootWindowHostX11::CopyAreaToSkCanvas( - const gfx::Rect& source_bounds, - const gfx::Point& dest_offset, - SkCanvas* canvas) { - NOTIMPLEMENTED(); - return false; -} - void DesktopRootWindowHostX11::PostNativeEvent( const base::NativeEvent& native_event) { DCHECK(xwindow_); @@ -814,7 +832,7 @@ void DesktopRootWindowHostX11::InitX11Window( CopyFromParent, // visual attribute_mask, &swa); - base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_); + base::MessagePumpX11::Current()->AddDispatcherForWindow(this, xwindow_); // TODO(erg): Maybe need to set a ViewProp here like in RWHL::RWHL(). @@ -877,6 +895,11 @@ void DesktopRootWindowHostX11::InitX11Window( PropModeAppend, reinterpret_cast<unsigned char*>(&atom), 1); } + + if (!params.wm_class_name.empty() || !params.wm_class_class.empty()) { + ui::SetWindowClassHint( + xdisplay_, xwindow_, params.wm_class_name, params.wm_class_class); + } } // TODO(erg): This method should basically be everything I need form @@ -903,25 +926,18 @@ aura::RootWindow* DesktopRootWindowHostX11::InitRootWindow( native_widget_delegate_->OnNativeWidgetCreated(true); - capture_client_.reset(new views::DesktopCaptureClient(root_window_)); - aura::client::SetCaptureClient(root_window_, capture_client_.get()); + desktop_native_widget_aura_->CreateCaptureClient(root_window_); // Ensure that the X11DesktopHandler exists so that it dispatches activation // messages to us. X11DesktopHandler::get(); - if (corewm::UseFocusControllerOnDesktop()) { - corewm::FocusController* focus_controller = - new corewm::FocusController(new DesktopFocusRules); - focus_client_.reset(focus_controller); - aura::client::SetFocusClient(root_window_, focus_controller); - aura::client::SetActivationClient(root_window_, focus_controller); - root_window_->AddPreTargetHandler(focus_controller); - } else { - focus_client_.reset(new aura::FocusManager); - aura::client::SetFocusClient(root_window_, focus_client_.get()); - activation_client_.reset(new DesktopActivationClient(root_window_)); - } + corewm::FocusController* focus_controller = + new corewm::FocusController(new DesktopFocusRules(content_window_)); + focus_client_.reset(focus_controller); + aura::client::SetFocusClient(root_window_, focus_controller); + aura::client::SetActivationClient(root_window_, focus_controller); + root_window_->AddPreTargetHandler(focus_controller); dispatcher_client_.reset(new DesktopDispatcherClient); aura::client::SetDispatcherClient(root_window_, @@ -950,8 +966,7 @@ aura::RootWindow* DesktopRootWindowHostX11::InitRootWindow( aura::client::SetDragDropClient(root_window_, drag_drop_client_.get()); // TODO(erg): Unify this code once the other consumer goes away. - x11_window_event_filter_.reset( - new X11WindowEventFilter(root_window_, activation_client_.get())); + x11_window_event_filter_.reset(new X11WindowEventFilter(root_window_)); x11_window_event_filter_->SetUseHostWindowBorders(false); desktop_native_widget_aura_->root_window_event_filter()->AddHandler( x11_window_event_filter_.get()); @@ -1303,6 +1318,8 @@ bool DesktopRootWindowHostX11::Dispatch(const base::NativeEvent& event) { restored_bounds_ = previous_bounds_; } + is_fullscreen_ = HasWMSpecProperty("_NET_WM_STATE_FULLSCREEN"); + // Now that we have different window properties, we may need to // relayout the window. (The windows code doesn't need this because // their window change is synchronous.) @@ -1340,13 +1357,13 @@ DesktopRootWindowHost* DesktopRootWindowHost::Create( DesktopNativeWidgetAura* desktop_native_widget_aura, const gfx::Rect& initial_bounds) { return new DesktopRootWindowHostX11(native_widget_delegate, - desktop_native_widget_aura, - initial_bounds); + desktop_native_widget_aura, + initial_bounds); } // static ui::NativeTheme* DesktopRootWindowHost::GetNativeTheme(aura::Window* window) { - const ui::LinuxUI* linux_ui = ui::LinuxUI::instance(); + const views::LinuxUI* linux_ui = views::LinuxUI::instance(); if (linux_ui) { ui::NativeTheme* native_theme = linux_ui->GetNativeTheme(); if (native_theme) diff --git a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_x11.h b/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_x11.h index e1dcc766930..ded7e98ca68 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_x11.h +++ b/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_x11.h @@ -29,8 +29,6 @@ class ScreenPositionClient; } namespace views { -class DesktopActivationClient; -class DesktopCaptureClient; class DesktopDragDropClientAuraX11; class DesktopDispatcherClient; class DesktopRootWindowHostObserverX11; @@ -121,9 +119,9 @@ class VIEWS_EXPORT DesktopRootWindowHostX11 : const gfx::ImageSkia& app_icon) OVERRIDE; virtual void InitModalType(ui::ModalType modal_type) OVERRIDE; virtual void FlashFrame(bool flash_frame) OVERRIDE; + virtual void OnRootViewLayout() const OVERRIDE; virtual void OnNativeWidgetFocus() OVERRIDE; virtual void OnNativeWidgetBlur() OVERRIDE; - virtual void SetInactiveRenderingDisabled(bool disable_inactive) OVERRIDE; // Overridden from aura::RootWindowHost: virtual void SetDelegate(aura::RootWindowHostDelegate* delegate) OVERRIDE; @@ -146,9 +144,6 @@ class VIEWS_EXPORT DesktopRootWindowHostX11 : virtual void OnCursorVisibilityChanged(bool show) OVERRIDE; virtual void MoveCursorTo(const gfx::Point& location) OVERRIDE; virtual void SetFocusWhenShown(bool focus_when_shown) OVERRIDE; - virtual bool CopyAreaToSkCanvas(const gfx::Rect& source_bounds, - const gfx::Point& dest_offset, - SkCanvas* canvas) OVERRIDE; virtual void PostNativeEvent(const base::NativeEvent& native_event) OVERRIDE; virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE; virtual void PrepareForShutdown() OVERRIDE; @@ -193,7 +188,7 @@ private: // X11 things // The display and the native X window hosting the root window. - Display* xdisplay_; + XDisplay* xdisplay_; ::Window xwindow_; // The native root window. @@ -224,13 +219,15 @@ private: // The window manager state bits. std::set< ::Atom> window_properties_; + // Local flag for fullscreen state to avoid a state mismatch between + // server and local window_properties_ during app-initiated fullscreen. + bool is_fullscreen_; + // We are owned by the RootWindow, but we have to have a back pointer to it. aura::RootWindow* root_window_; // aura:: objects that we own. - scoped_ptr<DesktopCaptureClient> capture_client_; scoped_ptr<aura::client::FocusClient> focus_client_; - scoped_ptr<DesktopActivationClient> activation_client_; scoped_ptr<views::corewm::CursorManager> cursor_client_; scoped_ptr<DesktopDispatcherClient> dispatcher_client_; scoped_ptr<aura::client::ScreenPositionClient> position_client_; diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_ozone.cc b/chromium/ui/views/widget/desktop_aura/desktop_screen_ozone.cc new file mode 100644 index 00000000000..5542178baaa --- /dev/null +++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_ozone.cc @@ -0,0 +1,15 @@ +// 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 "ui/views/widget/desktop_aura/desktop_screen.h" + +#include "ui/gfx/ozone/surface_factory_ozone.h" + +namespace views { + +gfx::Screen* CreateDesktopScreen() { + return gfx::SurfaceFactoryOzone::GetInstance()->CreateDesktopScreen(); +} + +} // namespace views diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc index 77dbaa497a7..880b3d05a98 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc +++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc @@ -12,17 +12,17 @@ #include "base/logging.h" #include "ui/aura/root_window.h" #include "ui/aura/root_window_host.h" -#include "ui/base/x/x11_util.h" #include "ui/gfx/display.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/screen.h" +#include "ui/gfx/x/x11_types.h" namespace { // TODO(erg): This method is a temporary hack, until we can reliably extract // location data out of XRandR. gfx::Size GetPrimaryDisplaySize() { - ::Display* display = ui::GetXDisplay(); + ::XDisplay* display = gfx::GetXDisplay(); ::Screen* screen = DefaultScreenOfDisplay(display); int width = WidthOfScreen(screen); int height = HeightOfScreen(screen); @@ -38,8 +38,11 @@ class DesktopScreenX11 : public gfx::Screen { // Overridden from gfx::Screen: virtual bool IsDIPEnabled() OVERRIDE; virtual gfx::Point GetCursorScreenPoint() OVERRIDE; - virtual gfx::NativeWindow GetWindowAtCursorScreenPoint() OVERRIDE; - virtual int GetNumDisplays() OVERRIDE; + virtual gfx::NativeWindow GetWindowUnderCursor() OVERRIDE; + virtual gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) + OVERRIDE; + virtual int GetNumDisplays() const OVERRIDE; + virtual std::vector<gfx::Display> GetAllDisplays() const OVERRIDE; virtual gfx::Display GetDisplayNearestWindow( gfx::NativeView window) const OVERRIDE; virtual gfx::Display GetDisplayNearestPoint( @@ -71,7 +74,7 @@ bool DesktopScreenX11::IsDIPEnabled() { } gfx::Point DesktopScreenX11::GetCursorScreenPoint() { - Display* display = ui::GetXDisplay(); + XDisplay* display = gfx::GetXDisplay(); ::Window root, child; int root_x, root_y, win_x, win_y; @@ -89,18 +92,29 @@ gfx::Point DesktopScreenX11::GetCursorScreenPoint() { return gfx::Point(root_x, root_y); } -gfx::NativeWindow DesktopScreenX11::GetWindowAtCursorScreenPoint() { +gfx::NativeWindow DesktopScreenX11::GetWindowUnderCursor() { // TODO(erg): Implement using the discussion at // http://codereview.chromium.org/10279005/ return NULL; } -int DesktopScreenX11::GetNumDisplays() { +gfx::NativeWindow DesktopScreenX11::GetWindowAtScreenPoint( + const gfx::Point& point) { + NOTIMPLEMENTED(); + return NULL; +} + +int DesktopScreenX11::GetNumDisplays() const { // TODO(erg): Figure this out with oshima or piman because I have no clue // about the XRandR implications here. return 1; } +std::vector<gfx::Display> DesktopScreenX11::GetAllDisplays() const { + // TODO(erg): Do the right thing once we know what that is. + return std::vector<gfx::Display>(1, GetPrimaryDisplay()); +} + gfx::Display DesktopScreenX11::GetDisplayNearestWindow( gfx::NativeView window) const { // TODO(erg): Do the right thing once we know what that is. diff --git a/chromium/ui/views/widget/desktop_aura/scoped_tooltip_client.cc b/chromium/ui/views/widget/desktop_aura/scoped_tooltip_client.cc new file mode 100644 index 00000000000..cf131022d89 --- /dev/null +++ b/chromium/ui/views/widget/desktop_aura/scoped_tooltip_client.cc @@ -0,0 +1,37 @@ +// 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 "ui/views/widget/desktop_aura/scoped_tooltip_client.h" + +#include "ui/aura/root_window.h" +#include "ui/views/corewm/tooltip_controller.h" + +namespace views { + +// static +corewm::TooltipController* ScopedTooltipClient::tooltip_controller_ = NULL; + +// static +int ScopedTooltipClient::scoped_tooltip_client_count_ = 0; + +ScopedTooltipClient::ScopedTooltipClient(aura::RootWindow* root_window) + : root_window_(root_window) { + if (scoped_tooltip_client_count_++ == 0) { + tooltip_controller_ = + new corewm::TooltipController(gfx::SCREEN_TYPE_NATIVE); + } + aura::client::SetTooltipClient(root_window_, tooltip_controller_); + root_window_->AddPreTargetHandler(tooltip_controller_); +} + +ScopedTooltipClient::~ScopedTooltipClient() { + root_window_->RemovePreTargetHandler(tooltip_controller_); + aura::client::SetTooltipClient(root_window_, NULL); + if (--scoped_tooltip_client_count_ == 0) { + delete tooltip_controller_; + tooltip_controller_ = NULL; + } +} + +} // namespace views diff --git a/chromium/ui/views/widget/desktop_aura/scoped_tooltip_client.h b/chromium/ui/views/widget/desktop_aura/scoped_tooltip_client.h new file mode 100644 index 00000000000..bb3e57b9d2c --- /dev/null +++ b/chromium/ui/views/widget/desktop_aura/scoped_tooltip_client.h @@ -0,0 +1,43 @@ +// 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. + +#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_SCOPED_TOOLTIP_CLIENT_H_ +#define UI_VIEWS_WIDGET_DESKTOP_AURA_SCOPED_TOOLTIP_CLIENT_H_ + +#include "base/basictypes.h" + +namespace aura { +class RootWindow; +} + +namespace views { + +namespace corewm { +class TooltipController; +} + +// ScopedTooltipClient is responsible for installing a TooltipClient +// implementation on a RootWindow. Additionally it ensures only one +// TooltipController is only ever created. In this way all +// DesktopNativeWidgetAuras share the same TooltipClient. +class ScopedTooltipClient { + public: + explicit ScopedTooltipClient(aura::RootWindow* root_window); + ~ScopedTooltipClient(); + + private: + // Single TooltipController. + static corewm::TooltipController* tooltip_controller_; + + // Number of ScopedTooltipClients created. + static int scoped_tooltip_client_count_; + + aura::RootWindow* root_window_; + + DISALLOW_COPY_AND_ASSIGN(ScopedTooltipClient); +}; + +} // namespace views + +#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_SCOPED_TOOLTIP_CLIENT_H_ diff --git a/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.cc b/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.cc index 46906992fce..0c965653f57 100644 --- a/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.cc +++ b/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.cc @@ -9,7 +9,6 @@ #include "ui/aura/focus_manager.h" #include "ui/aura/root_window.h" #include "ui/base/x/x11_util.h" -#include "ui/views/widget/desktop_aura/desktop_activation_client.h" #if !defined(OS_CHROMEOS) #include "ui/views/ime/input_method.h" @@ -39,11 +38,11 @@ X11DesktopHandler* X11DesktopHandler::get() { } X11DesktopHandler::X11DesktopHandler() - : xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()), + : xdisplay_(gfx::GetXDisplay()), x_root_window_(DefaultRootWindow(xdisplay_)), current_window_(None), atom_cache_(xdisplay_, kAtomsToCache) { - base::MessagePumpAuraX11::Current()->AddDispatcherForRootWindow(this); + base::MessagePumpX11::Current()->AddDispatcherForRootWindow(this); aura::Env::GetInstance()->AddObserver(this); XWindowAttributes attr; @@ -55,11 +54,11 @@ X11DesktopHandler::X11DesktopHandler() X11DesktopHandler::~X11DesktopHandler() { aura::Env::GetInstance()->RemoveObserver(this); - base::MessagePumpAuraX11::Current()->RemoveDispatcherForRootWindow(this); + base::MessagePumpX11::Current()->RemoveDispatcherForRootWindow(this); } void X11DesktopHandler::ActivateWindow(::Window window) { - DCHECK_EQ(base::MessagePumpAuraX11::GetDefaultXDisplay(), xdisplay_); + DCHECK_EQ(gfx::GetXDisplay(), xdisplay_); XEvent xclient; memset(&xclient, 0, sizeof(xclient)); diff --git a/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.h b/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.h index 8cda9eeaaab..e84b6d44a93 100644 --- a/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.h +++ b/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.h @@ -12,6 +12,7 @@ #include "base/message_loop/message_loop.h" #include "ui/aura/env_observer.h" #include "ui/base/x/x11_atom_cache.h" +#include "ui/gfx/x/x11_types.h" #include "ui/views/views_export.h" template <typename T> struct DefaultSingletonTraits; @@ -48,7 +49,7 @@ class VIEWS_EXPORT X11DesktopHandler : public base::MessageLoop::Dispatcher, void OnActiveWindowChanged(::Window window); // The display and the native X window hosting the root window. - Display* xdisplay_; + XDisplay* xdisplay_; // The native root window. ::Window x_root_window_; diff --git a/chromium/ui/views/widget/desktop_aura/x11_desktop_window_move_client.cc b/chromium/ui/views/widget/desktop_aura/x11_desktop_window_move_client.cc index d28de216dce..273372f0340 100644 --- a/chromium/ui/views/widget/desktop_aura/x11_desktop_window_move_client.cc +++ b/chromium/ui/views/widget/desktop_aura/x11_desktop_window_move_client.cc @@ -10,12 +10,12 @@ #include "base/debug/stack_trace.h" #include "base/message_loop/message_loop.h" -#include "base/message_loop/message_pump_aurax11.h" +#include "base/message_loop/message_pump_x11.h" #include "base/run_loop.h" #include "ui/aura/env.h" #include "ui/aura/root_window.h" -#include "ui/base/events/event.h" #include "ui/base/x/x11_util.h" +#include "ui/events/event.h" #include "ui/gfx/screen.h" namespace views { diff --git a/chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc b/chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc index d04dd88cb2f..177d137a2da 100644 --- a/chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc +++ b/chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc @@ -10,12 +10,12 @@ #include "base/debug/stack_trace.h" #include "base/message_loop/message_loop.h" -#include "base/message_loop/message_pump_aurax11.h" +#include "base/message_loop/message_pump_x11.h" #include "base/run_loop.h" #include "ui/aura/env.h" #include "ui/aura/root_window.h" -#include "ui/base/events/event.h" #include "ui/base/x/x11_util.h" +#include "ui/events/event.h" #include "ui/gfx/screen.h" namespace views { @@ -64,7 +64,7 @@ bool X11WholeScreenMoveLoop::RunMoveLoop(aura::Window* source, DCHECK(!in_move_loop_); // Can only handle one nested loop at a time. in_move_loop_ = true; - Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); + XDisplay* display = gfx::GetXDisplay(); // Creates an invisible, InputOnly toplevel window. This window will receive // all mouse movement for drags. It turns out that normal windows doing a @@ -83,12 +83,12 @@ bool X11WholeScreenMoveLoop::RunMoveLoop(aura::Window* source, -100, -100, 10, 10, 0, 0, InputOnly, CopyFromParent, attribute_mask, &swa); - base::MessagePumpAuraX11::Current()->AddDispatcherForWindow( + base::MessagePumpX11::Current()->AddDispatcherForWindow( this, grab_input_window_); // Wait for the window to be mapped. If we don't, XGrabPointer fails. XMapRaised(display, grab_input_window_); - base::MessagePumpAuraX11::Current()->BlockUntilWindowMapped( + base::MessagePumpX11::Current()->BlockUntilWindowMapped( grab_input_window_); if (!GrabPointerWithCursor(cursor)) @@ -116,10 +116,10 @@ void X11WholeScreenMoveLoop::EndMoveLoop() { // the chrome process. // Ungrab before we let go of the window. - Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); + XDisplay* display = gfx::GetXDisplay(); XUngrabPointer(display, CurrentTime); - base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow( + base::MessagePumpX11::Current()->RemoveDispatcherForWindow( grab_input_window_); delegate_->OnMoveLoopEnded(); XDestroyWindow(display, grab_input_window_); @@ -129,7 +129,7 @@ void X11WholeScreenMoveLoop::EndMoveLoop() { } bool X11WholeScreenMoveLoop::GrabPointerWithCursor(gfx::NativeCursor cursor) { - Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); + XDisplay* display = gfx::GetXDisplay(); XGrabServer(display); XUngrabPointer(display, CurrentTime); int ret = XGrabPointer( diff --git a/chromium/ui/views/widget/desktop_aura/x11_window_event_filter.cc b/chromium/ui/views/widget/desktop_aura/x11_window_event_filter.cc index 3495b04bc58..740e1204df0 100644 --- a/chromium/ui/views/widget/desktop_aura/x11_window_event_filter.cc +++ b/chromium/ui/views/widget/desktop_aura/x11_window_event_filter.cc @@ -9,13 +9,12 @@ #include <X11/Xatom.h> #include <X11/Xlib.h> -#include "base/message_loop/message_pump_aurax11.h" #include "ui/aura/root_window.h" #include "ui/aura/window_delegate.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_utils.h" #include "ui/base/hit_test.h" -#include "ui/views/widget/desktop_aura/desktop_activation_client.h" +#include "ui/events/event.h" +#include "ui/events/event_utils.h" +#include "ui/gfx/x/x11_types.h" #include "ui/views/widget/native_widget_aura.h" namespace { @@ -59,10 +58,8 @@ const char* kAtomsToCache[] = { namespace views { X11WindowEventFilter::X11WindowEventFilter( - aura::RootWindow* root_window, - DesktopActivationClient* activation_client) - : activation_client_(activation_client), - xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()), + aura::RootWindow* root_window) + : xdisplay_(gfx::GetXDisplay()), xwindow_(root_window->GetAcceleratedWidget()), x_root_window_(DefaultRootWindow(xdisplay_)), atom_cache_(xdisplay_, kAtomsToCache), @@ -79,7 +76,7 @@ void X11WindowEventFilter::SetUseHostWindowBorders(bool use_os_border) { motif_hints.decorations = use_os_border ? 1 : 0; ::Atom hint_atom = atom_cache_.GetAtom("_MOTIF_WM_HINTS"); - XChangeProperty(base::MessagePumpAuraX11::GetDefaultXDisplay(), + XChangeProperty(gfx::GetXDisplay(), xwindow_, hint_atom, hint_atom, diff --git a/chromium/ui/views/widget/desktop_aura/x11_window_event_filter.h b/chromium/ui/views/widget/desktop_aura/x11_window_event_filter.h index a6bdce8d3c8..9fab5a6fca0 100644 --- a/chromium/ui/views/widget/desktop_aura/x11_window_event_filter.h +++ b/chromium/ui/views/widget/desktop_aura/x11_window_event_filter.h @@ -11,8 +11,9 @@ #include "base/compiler_specific.h" #include "base/message_loop/message_loop.h" -#include "ui/base/events/event_handler.h" #include "ui/base/x/x11_atom_cache.h" +#include "ui/events/event_handler.h" +#include "ui/gfx/x/x11_types.h" #include "ui/views/views_export.h" namespace aura { @@ -25,14 +26,12 @@ class Point; } namespace views { -class DesktopActivationClient; class NativeWidgetAura; // An EventFilter that sets properties on X11 windows. class VIEWS_EXPORT X11WindowEventFilter : public ui::EventHandler { public: - explicit X11WindowEventFilter(aura::RootWindow* root_window, - DesktopActivationClient* activation_client); + explicit X11WindowEventFilter(aura::RootWindow* root_window); virtual ~X11WindowEventFilter(); // Changes whether borders are shown on this |root_window|. @@ -47,10 +46,8 @@ class VIEWS_EXPORT X11WindowEventFilter : public ui::EventHandler { bool DispatchHostWindowDragMovement(int hittest, const gfx::Point& screen_location); - DesktopActivationClient* activation_client_; - // The display and the native X window hosting the root window. - Display* xdisplay_; + XDisplay* xdisplay_; ::Window xwindow_; // The native root window. diff --git a/chromium/ui/views/widget/drop_helper.cc b/chromium/ui/views/widget/drop_helper.cc index e4493a30b48..ace1f900a70 100644 --- a/chromium/ui/views/widget/drop_helper.cc +++ b/chromium/ui/views/widget/drop_helper.cc @@ -99,7 +99,7 @@ View* DropHelper::CalculateTargetViewImpl( (!view->enabled() || !view->CanDrop(data))) { view = view->parent(); } -#elif !defined(OS_MACOSX) +#else int formats = 0; std::set<OSExchangeData::CustomFormat> custom_formats; while (view && view != target_view_) { diff --git a/chromium/ui/views/widget/monitor_win.cc b/chromium/ui/views/widget/monitor_win.cc index c183cb0f6db..1292692d9f3 100644 --- a/chromium/ui/views/widget/monitor_win.cc +++ b/chromium/ui/views/widget/monitor_win.cc @@ -7,6 +7,7 @@ #include <shellapi.h> #include "base/logging.h" +#include "base/win/win_util.h" #include "ui/gfx/rect.h" namespace views { @@ -17,7 +18,7 @@ gfx::Rect GetMonitorBoundsForRect(const gfx::Rect& rect) { if (monitor) { MONITORINFO mi = {0}; mi.cbSize = sizeof(mi); - GetMonitorInfo(monitor, &mi); + base::win::GetMonitorInfoWrapper(monitor, &mi); return gfx::Rect(mi.rcWork); } NOTREACHED(); diff --git a/chromium/ui/views/widget/native_widget_aura.cc b/chromium/ui/views/widget/native_widget_aura.cc index 8c9ad02b899..5c5136bf604 100644 --- a/chromium/ui/views/widget/native_widget_aura.cc +++ b/chromium/ui/views/widget/native_widget_aura.cc @@ -21,9 +21,9 @@ #include "ui/aura/window.h" #include "ui/aura/window_observer.h" #include "ui/base/dragdrop/os_exchange_data.h" -#include "ui/base/events/event.h" #include "ui/base/ui_base_types.h" #include "ui/compositor/layer.h" +#include "ui/events/event.h" #include "ui/gfx/canvas.h" #include "ui/gfx/font.h" #include "ui/gfx/screen.h" @@ -95,6 +95,13 @@ gfx::Font NativeWidgetAura::GetWindowTitleFont() { #endif } +// static +void NativeWidgetAura::RegisterNativeWidgetForWindow( + internal::NativeWidgetPrivate* native_widget, + aura::Window* window) { + window->set_user_data(native_widget); +} + //////////////////////////////////////////////////////////////////////////////// // NativeWidgetAura, internal::NativeWidgetPrivate implementation: @@ -105,7 +112,7 @@ void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) { ownership_ = params.ownership; - window_->set_user_data(this); + RegisterNativeWidgetForWindow(this, window_); window_->SetType(GetAuraWindowTypeForWidgetType(params.type)); window_->SetProperty(aura::client::kShowStateKey, params.show_state); if (params.type == Widget::InitParams::TYPE_BUBBLE) @@ -162,10 +169,8 @@ void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) { params.type != Widget::InitParams::TYPE_CONTROL && params.type != Widget::InitParams::TYPE_TOOLTIP; DCHECK(GetWidget()->GetRootView()); -#if !defined(OS_MACOSX) if (params.type != Widget::InitParams::TYPE_TOOLTIP) tooltip_manager_.reset(new views::TooltipManagerAura(window_, GetWidget())); -#endif // !defined(OS_MACOSX) drop_helper_.reset(new DropHelper(GetWidget()->GetRootView())); if (params.type != Widget::InitParams::TYPE_TOOLTIP && @@ -222,15 +227,15 @@ Widget* NativeWidgetAura::GetTopLevelWidget() { } const ui::Compositor* NativeWidgetAura::GetCompositor() const { - return window_->layer()->GetCompositor(); + return window_ ? window_->layer()->GetCompositor() : NULL; } ui::Compositor* NativeWidgetAura::GetCompositor() { - return window_->layer()->GetCompositor(); + return window_ ? window_->layer()->GetCompositor() : NULL; } ui::Layer* NativeWidgetAura::GetLayer() { - return window_->layer(); + return window_ ? window_->layer() : NULL; } void NativeWidgetAura::ReorderNativeViews() { @@ -256,18 +261,22 @@ TooltipManager* NativeWidgetAura::GetTooltipManager() const { } void NativeWidgetAura::SetCapture() { - window_->SetCapture(); + if (window_) + window_->SetCapture(); } void NativeWidgetAura::ReleaseCapture() { - window_->ReleaseCapture(); + if (window_) + window_->ReleaseCapture(); } bool NativeWidgetAura::HasCapture() const { - return window_->HasCapture(); + return window_ && window_->HasCapture(); } InputMethod* NativeWidgetAura::CreateInputMethod() { + if (!window_) + return NULL; aura::RootWindow* root_window = window_->GetRootWindow(); ui::InputMethod* host = root_window->GetProperty(aura::client::kRootWindowInputMethodKey); @@ -279,6 +288,9 @@ internal::InputMethodDelegate* NativeWidgetAura::GetInputMethodDelegate() { } void NativeWidgetAura::CenterWindow(const gfx::Size& size) { + if (!window_) + return; + gfx::Rect parent_bounds(window_->parent()->GetBoundsInRootWindow()); // When centering window, we take the intersection of the host and // the parent. We assume the root window represents the visible @@ -330,11 +342,13 @@ void NativeWidgetAura::GetWindowPlacement( ui::WindowShowState* show_state) const { // The interface specifies returning restored bounds, not current bounds. *bounds = GetRestoredBounds(); - *show_state = window_->GetProperty(aura::client::kShowStateKey); + *show_state = window_ ? window_->GetProperty(aura::client::kShowStateKey) : + ui::SHOW_STATE_DEFAULT; } void NativeWidgetAura::SetWindowTitle(const string16& title) { - window_->set_title(title); + if (window_) + window_->set_title(title); } void NativeWidgetAura::SetWindowIcons(const gfx::ImageSkia& window_icon, @@ -348,16 +362,19 @@ void NativeWidgetAura::InitModalType(ui::ModalType modal_type) { } gfx::Rect NativeWidgetAura::GetWindowBoundsInScreen() const { - return window_->GetBoundsInScreen(); + return window_ ? window_->GetBoundsInScreen() : gfx::Rect(); } gfx::Rect NativeWidgetAura::GetClientAreaBoundsInScreen() const { // View-to-screen coordinate system transformations depend on this returning // the full window bounds, for example View::ConvertPointToScreen(). - return window_->GetBoundsInScreen(); + return window_ ? window_->GetBoundsInScreen() : gfx::Rect(); } gfx::Rect NativeWidgetAura::GetRestoredBounds() const { + if (!window_) + return gfx::Rect(); + // Restored bounds should only be relevant if the window is minimized or // maximized. However, in some places the code expects GetRestoredBounds() // to return the current window bounds if the window is not in either state. @@ -372,6 +389,9 @@ gfx::Rect NativeWidgetAura::GetRestoredBounds() const { } void NativeWidgetAura::SetBounds(const gfx::Rect& bounds) { + if (!window_) + return; + aura::RootWindow* root = window_->GetRootWindow(); if (root) { aura::client::ScreenPositionClient* screen_position_client = @@ -387,20 +407,24 @@ void NativeWidgetAura::SetBounds(const gfx::Rect& bounds) { } void NativeWidgetAura::SetSize(const gfx::Size& size) { - window_->SetBounds(gfx::Rect(window_->bounds().origin(), size)); + if (window_) + window_->SetBounds(gfx::Rect(window_->bounds().origin(), size)); } void NativeWidgetAura::StackAbove(gfx::NativeView native_view) { - if (window_->parent() && window_->parent() == native_view->parent()) + if (window_ && window_->parent() && + window_->parent() == native_view->parent()) window_->parent()->StackChildAbove(window_, native_view); } void NativeWidgetAura::StackAtTop() { - window_->parent()->StackChildAtTop(window_); + if (window_) + window_->parent()->StackChildAtTop(window_); } void NativeWidgetAura::StackBelow(gfx::NativeView native_view) { - if (window_->parent() && window_->parent() == native_view->parent()) + if (window_ && window_->parent() && + window_->parent() == native_view->parent()) window_->parent()->StackChildBelow(window_, native_view); } @@ -438,7 +462,8 @@ void NativeWidgetAura::Show() { } void NativeWidgetAura::Hide() { - window_->Hide(); + if (window_) + window_->Hide(); } void NativeWidgetAura::ShowMaximizedWithBounds( @@ -448,6 +473,9 @@ void NativeWidgetAura::ShowMaximizedWithBounds( } void NativeWidgetAura::ShowWithWindowState(ui::WindowShowState state) { + if (!window_) + return; + if (state == ui::SHOW_STATE_MAXIMIZED || state == ui::SHOW_STATE_FULLSCREEN) window_->SetProperty(aura::client::kShowStateKey, state); window_->Show(); @@ -466,10 +494,13 @@ void NativeWidgetAura::ShowWithWindowState(ui::WindowShowState state) { } bool NativeWidgetAura::IsVisible() const { - return window_->IsVisible(); + return window_ && window_->IsVisible(); } void NativeWidgetAura::Activate() { + if (!window_) + return; + // We don't necessarily have a root window yet. This can happen with // constrained windows. if (window_->GetRootWindow()) { @@ -481,43 +512,55 @@ void NativeWidgetAura::Activate() { } void NativeWidgetAura::Deactivate() { + if (!window_) + return; aura::client::GetActivationClient(window_->GetRootWindow())->DeactivateWindow( window_); } bool NativeWidgetAura::IsActive() const { - return aura::client::GetActivationClient(window_->GetRootWindow())-> - GetActiveWindow() == window_; + if (!window_) + return false; + + // We may up here during destruction of the root, in which case + // GetRootWindow() returns NULL (~RootWindow() has run and we're in ~Window). + aura::RootWindow* root = window_->GetRootWindow(); + return root && + aura::client::GetActivationClient(root)->GetActiveWindow() == window_; } void NativeWidgetAura::SetAlwaysOnTop(bool on_top) { - window_->SetProperty(aura::client::kAlwaysOnTopKey, on_top); + if (window_) + window_->SetProperty(aura::client::kAlwaysOnTopKey, on_top); } void NativeWidgetAura::Maximize() { - window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); + if (window_) + window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); } void NativeWidgetAura::Minimize() { - window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); + if (window_) + window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); } bool NativeWidgetAura::IsMaximized() const { - return window_->GetProperty(aura::client::kShowStateKey) == + return window_ && window_->GetProperty(aura::client::kShowStateKey) == ui::SHOW_STATE_MAXIMIZED; } bool NativeWidgetAura::IsMinimized() const { - return window_->GetProperty(aura::client::kShowStateKey) == + return window_ && window_->GetProperty(aura::client::kShowStateKey) == ui::SHOW_STATE_MINIMIZED; } void NativeWidgetAura::Restore() { - window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); + if (window_) + window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); } void NativeWidgetAura::SetFullscreen(bool fullscreen) { - if (IsFullscreen() == fullscreen) + if (!window_ || IsFullscreen() == fullscreen) return; // Nothing to do. // Save window state before entering full screen so that it could restored @@ -531,12 +574,13 @@ void NativeWidgetAura::SetFullscreen(bool fullscreen) { } bool NativeWidgetAura::IsFullscreen() const { - return window_->GetProperty(aura::client::kShowStateKey) == + return window_ && window_->GetProperty(aura::client::kShowStateKey) == ui::SHOW_STATE_FULLSCREEN; } void NativeWidgetAura::SetOpacity(unsigned char opacity) { - window_->layer()->SetOpacity(opacity / 255.0); + if (window_) + window_->layer()->SetOpacity(opacity / 255.0); } void NativeWidgetAura::SetUseDragFrame(bool use_drag_frame) { @@ -544,7 +588,8 @@ void NativeWidgetAura::SetUseDragFrame(bool use_drag_frame) { } void NativeWidgetAura::FlashFrame(bool flash) { - window_->SetProperty(aura::client::kDrawAttentionKey, flash); + if (window_) + window_->SetProperty(aura::client::kDrawAttentionKey, flash); } void NativeWidgetAura::RunShellDrag(View* view, @@ -552,7 +597,8 @@ void NativeWidgetAura::RunShellDrag(View* view, const gfx::Point& location, int operation, ui::DragDropTypes::DragEventSource source) { - views::RunShellDrag(window_, data, location, operation, source); + if (window_) + views::RunShellDrag(window_, data, location, operation, source); } void NativeWidgetAura::SchedulePaintInRect(const gfx::Rect& rect) { @@ -569,6 +615,8 @@ void NativeWidgetAura::SetCursor(gfx::NativeCursor cursor) { } bool NativeWidgetAura::IsMouseEventsEnabled() const { + if (!window_) + return false; aura::client::CursorClient* cursor_client = aura::client::GetCursorClient(window_->GetRootWindow()); return cursor_client ? cursor_client->IsMouseEventsEnabled() : true; @@ -581,11 +629,16 @@ void NativeWidgetAura::ClearNativeFocus() { } gfx::Rect NativeWidgetAura::GetWorkAreaBoundsInScreen() const { - return gfx::Screen::GetScreenFor(GetNativeView())-> - GetDisplayNearestWindow(GetNativeView()).work_area(); + if (!window_) + return gfx::Rect(); + return gfx::Screen::GetScreenFor(window_)-> + GetDisplayNearestWindow(window_).work_area(); } void NativeWidgetAura::SetInactiveRenderingDisabled(bool value) { + if (!window_) + return; + if (!value) { active_window_observer_.reset(); } else { @@ -597,7 +650,7 @@ void NativeWidgetAura::SetInactiveRenderingDisabled(bool value) { Widget::MoveLoopResult NativeWidgetAura::RunMoveLoop( const gfx::Vector2d& drag_offset, Widget::MoveLoopSource source) { - if (window_->parent() && + if (window_ && window_->parent() && aura::client::GetWindowMoveClient(window_->parent())) { SetCapture(); aura::client::WindowMoveSource window_move_source = @@ -614,14 +667,15 @@ Widget::MoveLoopResult NativeWidgetAura::RunMoveLoop( } void NativeWidgetAura::EndMoveLoop() { - if (window_->parent() && + if (window_ && window_->parent() && aura::client::GetWindowMoveClient(window_->parent())) { aura::client::GetWindowMoveClient(window_->parent())->EndMoveLoop(); } } void NativeWidgetAura::SetVisibilityChangedAnimationsEnabled(bool value) { - window_->SetProperty(aura::client::kAnimationsDisabledKey, !value); + if (window_) + window_->SetProperty(aura::client::kAnimationsDisabledKey, !value); } ui::NativeTheme* NativeWidgetAura::GetNativeTheme() const { @@ -632,6 +686,9 @@ ui::NativeTheme* NativeWidgetAura::GetNativeTheme() const { #endif } +void NativeWidgetAura::OnRootViewLayout() const { +} + //////////////////////////////////////////////////////////////////////////////// // NativeWidgetAura, views::InputMethodDelegate implementation: @@ -748,17 +805,15 @@ void NativeWidgetAura::GetHitTestMask(gfx::Path* mask) const { delegate_->GetHitTestMask(mask); } -scoped_refptr<ui::Texture> NativeWidgetAura::CopyTexture() { - // The layer we create doesn't have an external texture, so this should never - // get invoked. - NOTREACHED(); - return scoped_refptr<ui::Texture>(); +void NativeWidgetAura::DidRecreateLayer(ui::Layer *old_layer, + ui::Layer *new_layer) { } //////////////////////////////////////////////////////////////////////////////// // NativeWidgetAura, ui::EventHandler implementation: void NativeWidgetAura::OnKeyEvent(ui::KeyEvent* event) { + DCHECK(window_); if (event->is_char()) { // If a ui::InputMethod object is attached to the root window, character // events are handled inside the object and are not passed to this function. @@ -775,6 +830,7 @@ void NativeWidgetAura::OnKeyEvent(ui::KeyEvent* event) { } void NativeWidgetAura::OnMouseEvent(ui::MouseEvent* event) { + DCHECK(window_); DCHECK(window_->IsVisible()); if (event->type() == ui::ET_MOUSEWHEEL) { delegate_->OnMouseEvent(event); @@ -792,11 +848,13 @@ void NativeWidgetAura::OnScrollEvent(ui::ScrollEvent* event) { } void NativeWidgetAura::OnTouchEvent(ui::TouchEvent* event) { + DCHECK(window_); DCHECK(window_->IsVisible()); delegate_->OnTouchEvent(event); } void NativeWidgetAura::OnGestureEvent(ui::GestureEvent* event) { + DCHECK(window_); DCHECK(window_->IsVisible()); delegate_->OnGestureEvent(event); } @@ -975,12 +1033,14 @@ NativeWidgetPrivate* NativeWidgetPrivate::CreateNativeWidget( // static NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeView( gfx::NativeView native_view) { + // Cast must match type supplied to RegisterNativeWidgetForWindow(). return reinterpret_cast<NativeWidgetPrivate*>(native_view->user_data()); } // static NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeWindow( gfx::NativeWindow native_window) { + // Cast must match type supplied to RegisterNativeWidgetForWindow(). return reinterpret_cast<NativeWidgetPrivate*>(native_window->user_data()); } @@ -1012,10 +1072,22 @@ void NativeWidgetPrivate::GetAllChildWidgets(gfx::NativeView native_view, const aura::Window::Windows& child_windows = native_view->children(); for (aura::Window::Windows::const_iterator i = child_windows.begin(); i != child_windows.end(); ++i) { - NativeWidgetAura* native_widget = - static_cast<NativeWidgetAura*>(GetNativeWidgetForNativeView(*i)); - if (native_widget) - children->insert(native_widget->GetWidget()); + GetAllChildWidgets((*i), children); + } +} + +// static +void NativeWidgetPrivate::GetAllOwnedWidgets(gfx::NativeView native_view, + Widget::Widgets* owned) { + const aura::Window::Windows& transient_children = + native_view->transient_children(); + for (aura::Window::Windows::const_iterator i = transient_children.begin(); + i != transient_children.end(); ++i) { + NativeWidgetPrivate* native_widget = static_cast<NativeWidgetPrivate*>( + GetNativeWidgetForNativeView(*i)); + if (native_widget && native_widget->GetWidget()) + owned->insert(native_widget->GetWidget()); + GetAllOwnedWidgets((*i), owned); } } @@ -1035,7 +1107,7 @@ void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view, // from their previous parent. for (Widget::Widgets::iterator it = widgets.begin(); it != widgets.end(); ++it) { - (*it)->NotifyNativeViewHierarchyChanged(false, previous_parent); + (*it)->NotifyNativeViewHierarchyWillChange(); } if (new_parent) { @@ -1060,7 +1132,7 @@ void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view, // And now, notify them that they have a brand new parent. for (Widget::Widgets::iterator it = widgets.begin(); it != widgets.end(); ++it) { - (*it)->NotifyNativeViewHierarchyChanged(true, new_parent); + (*it)->NotifyNativeViewHierarchyChanged(); } } diff --git a/chromium/ui/views/widget/native_widget_aura.h b/chromium/ui/views/widget/native_widget_aura.h index 57271e81a98..dfd3aaf44e6 100644 --- a/chromium/ui/views/widget/native_widget_aura.h +++ b/chromium/ui/views/widget/native_widget_aura.h @@ -12,7 +12,8 @@ #include "ui/aura/client/drag_drop_delegate.h" #include "ui/aura/client/focus_change_observer.h" #include "ui/aura/window_delegate.h" -#include "ui/base/events/event_constants.h" +#include "ui/base/cursor/cursor.h" +#include "ui/events/event_constants.h" #include "ui/views/ime/input_method_delegate.h" #include "ui/views/views_export.h" #include "ui/views/widget/native_widget_private.h" @@ -46,6 +47,12 @@ class VIEWS_EXPORT NativeWidgetAura // NativeWidgetWin. static gfx::Font GetWindowTitleFont(); + // Called internally by NativeWidgetAura and DesktopNativeWidgetAura to + // associate |native_widget| with |window|. + static void RegisterNativeWidgetForWindow( + internal::NativeWidgetPrivate* native_widget, + aura::Window* window); + // Overridden from internal::NativeWidgetPrivate: virtual void InitNativeWidget(const Widget::InitParams& params) OVERRIDE; virtual NonClientFrameView* CreateNonClientFrameView() OVERRIDE; @@ -125,6 +132,7 @@ class VIEWS_EXPORT NativeWidgetAura virtual void EndMoveLoop() OVERRIDE; virtual void SetVisibilityChangedAnimationsEnabled(bool value) OVERRIDE; virtual ui::NativeTheme* GetNativeTheme() const OVERRIDE; + virtual void OnRootViewLayout() const OVERRIDE; // Overridden from views::InputMethodDelegate: virtual void DispatchKeyEventPostIME(const ui::KeyEvent& key) OVERRIDE; @@ -148,7 +156,8 @@ class VIEWS_EXPORT NativeWidgetAura virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE; virtual bool HasHitTestMask() const OVERRIDE; virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE; - virtual scoped_refptr<ui::Texture> CopyTexture() OVERRIDE; + virtual void DidRecreateLayer(ui::Layer* old_layer, + ui::Layer* new_layer) OVERRIDE; // Overridden from ui::EventHandler: virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; @@ -189,6 +198,9 @@ class VIEWS_EXPORT NativeWidgetAura internal::NativeWidgetDelegate* delegate_; + // WARNING: set to NULL when destroyed. As the Widget is not necessarily + // destroyed along with |window_| all usage of |window_| should first verify + // non-NULL. aura::Window* window_; // See class documentation for Widget in widget.h for a note about ownership. diff --git a/chromium/ui/views/widget/native_widget_aura_unittest.cc b/chromium/ui/views/widget/native_widget_aura_unittest.cc index 612616bc2c0..de63a0b8a90 100644 --- a/chromium/ui/views/widget/native_widget_aura_unittest.cc +++ b/chromium/ui/views/widget/native_widget_aura_unittest.cc @@ -15,7 +15,7 @@ #include "ui/aura/root_window.h" #include "ui/aura/test/aura_test_helper.h" #include "ui/aura/window.h" -#include "ui/base/events/event.h" +#include "ui/events/event.h" #include "ui/gfx/screen.h" #include "ui/views/layout/fill_layout.h" #include "ui/views/widget/root_view.h" diff --git a/chromium/ui/views/widget/native_widget_delegate.h b/chromium/ui/views/widget/native_widget_delegate.h index c1fd073370e..914b575f30d 100644 --- a/chromium/ui/views/widget/native_widget_delegate.h +++ b/chromium/ui/views/widget/native_widget_delegate.h @@ -7,7 +7,7 @@ #include <vector> -#include "ui/base/events/event_constants.h" +#include "ui/events/event_constants.h" #include "ui/views/views_export.h" namespace gfx { @@ -61,6 +61,9 @@ class VIEWS_EXPORT NativeWidgetDelegate { virtual void OnNativeFocus(gfx::NativeView focused_view) = 0; virtual void OnNativeBlur(gfx::NativeView focused_view) = 0; + // Called when the window is about to be shown/hidden. + virtual void OnNativeWidgetVisibilityChanging(bool visible) = 0; + // Called when the window is shown/hidden. virtual void OnNativeWidgetVisibilityChanged(bool visible) = 0; diff --git a/chromium/ui/views/widget/native_widget_private.h b/chromium/ui/views/widget/native_widget_private.h index 3bdd6810cfc..4654b20e3f0 100644 --- a/chromium/ui/views/widget/native_widget_private.h +++ b/chromium/ui/views/widget/native_widget_private.h @@ -61,6 +61,8 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget { static void GetAllChildWidgets(gfx::NativeView native_view, Widget::Widgets* children); + static void GetAllOwnedWidgets(gfx::NativeView native_view, + Widget::Widgets* owned); static void ReparentNativeView(gfx::NativeView native_view, gfx::NativeView new_parent); @@ -213,6 +215,7 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget { virtual void EndMoveLoop() = 0; virtual void SetVisibilityChangedAnimationsEnabled(bool value) = 0; virtual ui::NativeTheme* GetNativeTheme() const = 0; + virtual void OnRootViewLayout() const = 0; // Overridden from NativeWidget: virtual internal::NativeWidgetPrivate* AsNativeWidgetPrivate() OVERRIDE; diff --git a/chromium/ui/views/widget/native_widget_win.cc b/chromium/ui/views/widget/native_widget_win.cc index d6ebdd6d664..53aed93a29a 100644 --- a/chromium/ui/views/widget/native_widget_win.cc +++ b/chromium/ui/views/widget/native_widget_win.cc @@ -18,22 +18,22 @@ #include "ui/base/dragdrop/drag_source_win.h" #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/base/dragdrop/os_exchange_data_provider_win.h" -#include "ui/base/events/event.h" #include "ui/base/ime/input_method_factory.h" -#include "ui/base/keycodes/keyboard_code_conversion_win.h" #include "ui/base/l10n/l10n_util_win.h" #include "ui/base/theme_provider.h" #include "ui/base/view_prop.h" -#include "ui/base/win/dpi.h" -#include "ui/base/win/hwnd_util.h" #include "ui/base/win/mouse_wheel_util.h" #include "ui/base/win/shell.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/keyboard_code_conversion_win.h" #include "ui/gfx/canvas.h" #include "ui/gfx/canvas_skia_paint.h" #include "ui/gfx/path.h" #include "ui/gfx/point_conversions.h" #include "ui/gfx/screen.h" #include "ui/gfx/size_conversions.h" +#include "ui/gfx/win/dpi.h" +#include "ui/gfx/win/hwnd_util.h" #include "ui/native_theme/native_theme.h" #include "ui/views/controls/native_control_win.h" #include "ui/views/controls/textfield/textfield.h" @@ -61,9 +61,10 @@ namespace views { namespace { -// Enumeration callback for NativeWidget::GetAllChildWidgets(). Called for each -// child HWND beneath the original HWND. -BOOL CALLBACK EnumerateChildWindowsForNativeWidgets(HWND hwnd, LPARAM l_param) { +// Enumeration callback for NativeWidget::GetAllChildWidgets() and +// NativeWidget::GetAllOwnedWidgets. Adds any HWNDs that correspond to +// Widgets to a set. +BOOL CALLBACK EnumerateNativeWidgets(HWND hwnd, LPARAM l_param) { Widget* widget = Widget::GetWidgetForNativeView(hwnd); if (widget) { Widget::Widgets* widgets = reinterpret_cast<Widget::Widgets*>(l_param); @@ -116,7 +117,7 @@ void NativeWidgetWin::Show(int show_state) { // NativeWidgetWin, NativeWidget implementation: void NativeWidgetWin::InitNativeWidget(const Widget::InitParams& params) { - gfx::Rect pixel_bounds = ui::win::DIPToScreenRect(params.bounds); + gfx::Rect pixel_bounds = gfx::win::DIPToScreenRect(params.bounds); Widget::InitParams params_in_pixel(params); params_in_pixel.bounds = pixel_bounds; SetInitParams(params_in_pixel); @@ -220,7 +221,7 @@ internal::InputMethodDelegate* NativeWidgetWin::GetInputMethodDelegate() { } void NativeWidgetWin::CenterWindow(const gfx::Size& size) { - gfx::Size size_in_pixels = ui::win::DIPToScreenSize(size); + gfx::Size size_in_pixels = gfx::win::DIPToScreenSize(size); message_handler_->CenterWindow(size_in_pixels); } @@ -228,7 +229,7 @@ void NativeWidgetWin::GetWindowPlacement( gfx::Rect* bounds, ui::WindowShowState* show_state) const { message_handler_->GetWindowPlacement(bounds, show_state); - *bounds = ui::win::ScreenToDIPRect(*bounds); + *bounds = gfx::win::ScreenToDIPRect(*bounds); } void NativeWidgetWin::SetWindowTitle(const string16& title) { @@ -246,21 +247,21 @@ void NativeWidgetWin::InitModalType(ui::ModalType modal_type) { gfx::Rect NativeWidgetWin::GetWindowBoundsInScreen() const { gfx::Rect bounds_in_pixels = message_handler_->GetWindowBoundsInScreen(); - return ui::win::ScreenToDIPRect(bounds_in_pixels); + return gfx::win::ScreenToDIPRect(bounds_in_pixels); } gfx::Rect NativeWidgetWin::GetClientAreaBoundsInScreen() const { gfx::Rect bounds_in_pixels = message_handler_->GetClientAreaBoundsInScreen(); - return ui::win::ScreenToDIPRect(bounds_in_pixels); + return gfx::win::ScreenToDIPRect(bounds_in_pixels); } gfx::Rect NativeWidgetWin::GetRestoredBounds() const { gfx::Rect bounds_in_pixels = message_handler_->GetRestoredBounds(); - return ui::win::ScreenToDIPRect(bounds_in_pixels); + return gfx::win::ScreenToDIPRect(bounds_in_pixels); } void NativeWidgetWin::SetBounds(const gfx::Rect& bounds) { - float scale = ui::win::GetDeviceScaleFactor(); + float scale = gfx::win::GetDeviceScaleFactor(); gfx::Rect bounds_in_pixels( gfx::ToCeiledPoint(gfx::ScalePoint(bounds.origin(), scale)), gfx::ToFlooredSize(gfx::ScaleSize(bounds.size(), scale))); @@ -305,7 +306,7 @@ void NativeWidgetWin::Hide() { void NativeWidgetWin::ShowMaximizedWithBounds( const gfx::Rect& restored_bounds) { - gfx::Rect pixel_bounds = ui::win::DIPToScreenRect(restored_bounds); + gfx::Rect pixel_bounds = gfx::win::DIPToScreenRect(restored_bounds); message_handler_->ShowMaximizedWithBounds(pixel_bounds); } @@ -412,7 +413,7 @@ void NativeWidgetWin::RunShellDrag(View* view, } void NativeWidgetWin::SchedulePaintInRect(const gfx::Rect& rect) { - gfx::Rect pixel_rect = ui::win::DIPToScreenRect(rect); + gfx::Rect pixel_rect = gfx::win::DIPToScreenRect(rect); message_handler_->SchedulePaintInRect(pixel_rect); } @@ -429,7 +430,7 @@ void NativeWidgetWin::ClearNativeFocus() { } gfx::Rect NativeWidgetWin::GetWorkAreaBoundsInScreen() const { - return ui::win::ScreenToDIPRect( + return gfx::win::ScreenToDIPRect( gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( GetNativeView()).work_area()); } @@ -456,6 +457,9 @@ ui::NativeTheme* NativeWidgetWin::GetNativeTheme() const { return ui::NativeTheme::instance(); } +void NativeWidgetWin::OnRootViewLayout() const { +} + //////////////////////////////////////////////////////////////////////////////// // NativeWidgetWin, NativeWidget implementation: @@ -566,7 +570,7 @@ bool NativeWidgetWin::WillProcessWorkAreaChange() const { } int NativeWidgetWin::GetNonClientComponent(const gfx::Point& point) const { - gfx::Point point_in_dip = ui::win::ScreenToDIPPoint(point); + gfx::Point point_in_dip = gfx::win::ScreenToDIPPoint(point); return delegate_->GetNonClientComponent(point_in_dip); } @@ -581,13 +585,13 @@ bool NativeWidgetWin::GetClientAreaInsets(gfx::Insets* insets) const { void NativeWidgetWin::GetMinMaxSize(gfx::Size* min_size, gfx::Size* max_size) const { - *min_size = ui::win::ScreenToDIPSize(delegate_->GetMinimumSize()); - *max_size = ui::win::ScreenToDIPSize(delegate_->GetMaximumSize()); + *min_size = gfx::win::ScreenToDIPSize(delegate_->GetMinimumSize()); + *max_size = gfx::win::ScreenToDIPSize(delegate_->GetMaximumSize()); } gfx::Size NativeWidgetWin::GetRootViewSize() const { gfx::Size pixel_size = GetWidget()->GetRootView()->size(); - return ui::win::ScreenToDIPSize(pixel_size); + return gfx::win::ScreenToDIPSize(pixel_size); } void NativeWidgetWin::ResetWindowControls() { @@ -717,12 +721,16 @@ void NativeWidgetWin::HandleWorkAreaChanged() { GetWidget()->widget_delegate()->OnWorkAreaChanged(); } +void NativeWidgetWin::HandleVisibilityChanging(bool visible) { + delegate_->OnNativeWidgetVisibilityChanging(visible); +} + void NativeWidgetWin::HandleVisibilityChanged(bool visible) { delegate_->OnNativeWidgetVisibilityChanged(visible); } void NativeWidgetWin::HandleClientSizeChanged(const gfx::Size& new_size) { - gfx::Size size_in_dip = ui::win::ScreenToDIPSize(new_size); + gfx::Size size_in_dip = gfx::win::ScreenToDIPSize(new_size); delegate_->OnNativeWidgetSizeChanged(size_in_dip); } @@ -747,8 +755,8 @@ void NativeWidgetWin::HandleNativeBlur(HWND focused_window) { bool NativeWidgetWin::HandleMouseEvent(const ui::MouseEvent& event) { static gfx::Transform scale_transform( - 1/ui::win::GetDeviceScaleFactor(), 0.0, - 0.0, 1/ui::win::GetDeviceScaleFactor(), + 1/gfx::win::GetDeviceScaleFactor(), 0.0, + 0.0, 1/gfx::win::GetDeviceScaleFactor(), 0.0, 0.0); if (event.IsMouseWheelEvent()) { ui::MouseWheelEvent dpi_event( @@ -780,9 +788,8 @@ bool NativeWidgetWin::HandleUntranslatedKeyEvent(const ui::KeyEvent& event) { return !!input_method; } -bool NativeWidgetWin::HandleTouchEvent(const ui::TouchEvent& event) { +void NativeWidgetWin::HandleTouchEvent(const ui::TouchEvent& event) { NOTREACHED() << "Touch events are not supported"; - return false; } bool NativeWidgetWin::HandleIMEMessage(UINT message, @@ -812,7 +819,7 @@ void NativeWidgetWin::HandleInputLanguageChange(DWORD character_set, } bool NativeWidgetWin::HandlePaintAccelerated(const gfx::Rect& invalid_rect) { - gfx::Rect dpi_rect = ui::win::ScreenToDIPRect(invalid_rect); + gfx::Rect dpi_rect = gfx::win::ScreenToDIPRect(invalid_rect); return delegate_->OnNativeWidgetPaintAccelerated(dpi_rect); } @@ -902,11 +909,11 @@ bool Widget::ConvertRect(const Widget* source, if (source_hwnd == target_hwnd) return true; - RECT win_rect = ui::win::DIPToScreenRect(*rect).ToRECT(); + RECT win_rect = gfx::win::DIPToScreenRect(*rect).ToRECT(); if (::MapWindowPoints(source_hwnd, target_hwnd, reinterpret_cast<LPPOINT>(&win_rect), sizeof(RECT)/sizeof(POINT))) { - *rect = ui::win::ScreenToDIPRect(gfx::Rect(win_rect)); + *rect = gfx::win::ScreenToDIPRect(gfx::Rect(win_rect)); return true; } return false; @@ -984,11 +991,26 @@ void NativeWidgetPrivate::GetAllChildWidgets(gfx::NativeView native_view, Widget* widget = Widget::GetWidgetForNativeView(native_view); if (widget) children->insert(widget); - EnumChildWindows(native_view, EnumerateChildWindowsForNativeWidgets, + EnumChildWindows(native_view, EnumerateNativeWidgets, reinterpret_cast<LPARAM>(children)); } // static +void NativeWidgetPrivate::GetAllOwnedWidgets(gfx::NativeView native_view, + Widget::Widgets* owned) { + if (!native_view) + return; + + Widget::Widgets all; + EnumWindows(EnumerateNativeWidgets, reinterpret_cast<LPARAM>(&all)); + for (Widget::Widgets::const_iterator iter = all.begin(); + iter != all.end(); ++iter) { + if (native_view == GetWindow((*iter)->GetNativeView(), GW_OWNER)) + owned->insert(*iter); + } +} + +// static void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view, gfx::NativeView new_parent) { if (!native_view) @@ -1005,9 +1027,7 @@ void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view, // from their previous parent. for (Widget::Widgets::iterator it = widgets.begin(); it != widgets.end(); ++it) { - // TODO(beng): Rename this notification to NotifyNativeViewChanging() - // and eliminate the bool parameter. - (*it)->NotifyNativeViewHierarchyChanged(false, previous_parent); + (*it)->NotifyNativeViewHierarchyWillChange(); } ::SetParent(native_view, new_parent); @@ -1015,7 +1035,7 @@ void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view, // And now, notify them that they have a brand new parent. for (Widget::Widgets::iterator it = widgets.begin(); it != widgets.end(); ++it) { - (*it)->NotifyNativeViewHierarchyChanged(true, new_parent); + (*it)->NotifyNativeViewHierarchyChanged(); } } diff --git a/chromium/ui/views/widget/native_widget_win.h b/chromium/ui/views/widget/native_widget_win.h index 81fa718ef41..cadc6fdb7a3 100644 --- a/chromium/ui/views/widget/native_widget_win.h +++ b/chromium/ui/views/widget/native_widget_win.h @@ -11,7 +11,7 @@ #include "base/memory/scoped_vector.h" #include "base/win/scoped_comptr.h" #include "base/win/win_util.h" -#include "ui/base/win/window_impl.h" +#include "ui/gfx/win/window_impl.h" #include "ui/views/widget/native_widget_private.h" #include "ui/views/win/hwnd_message_handler_delegate.h" @@ -146,6 +146,7 @@ class VIEWS_EXPORT NativeWidgetWin : public internal::NativeWidgetPrivate, virtual void EndMoveLoop() OVERRIDE; virtual void SetVisibilityChangedAnimationsEnabled(bool value) OVERRIDE; virtual ui::NativeTheme* GetNativeTheme() const OVERRIDE; + virtual void OnRootViewLayout() const OVERRIDE; // Overridden from NativeWidget: virtual ui::EventHandler* GetEventHandler() OVERRIDE; @@ -202,6 +203,7 @@ class VIEWS_EXPORT NativeWidgetWin : public internal::NativeWidgetPrivate, virtual void HandleEndWMSizeMove() OVERRIDE; virtual void HandleMove() OVERRIDE; virtual void HandleWorkAreaChanged() OVERRIDE; + virtual void HandleVisibilityChanging(bool visible) OVERRIDE; virtual void HandleVisibilityChanged(bool visible) OVERRIDE; virtual void HandleClientSizeChanged(const gfx::Size& new_size) OVERRIDE; virtual void HandleFrameChanged() OVERRIDE; @@ -210,7 +212,7 @@ class VIEWS_EXPORT NativeWidgetWin : public internal::NativeWidgetPrivate, virtual bool HandleMouseEvent(const ui::MouseEvent& event) OVERRIDE; virtual bool HandleKeyEvent(const ui::KeyEvent& event) OVERRIDE; virtual bool HandleUntranslatedKeyEvent(const ui::KeyEvent& event) OVERRIDE; - virtual bool HandleTouchEvent(const ui::TouchEvent& event) OVERRIDE; + virtual void HandleTouchEvent(const ui::TouchEvent& event) OVERRIDE; virtual bool HandleIMEMessage(UINT message, WPARAM w_param, LPARAM l_param, diff --git a/chromium/ui/views/widget/root_view.cc b/chromium/ui/views/widget/root_view.cc index b304c520b97..1185c755153 100644 --- a/chromium/ui/views/widget/root_view.cc +++ b/chromium/ui/views/widget/root_view.cc @@ -10,9 +10,9 @@ #include "base/message_loop/message_loop.h" #include "ui/base/accessibility/accessible_view_state.h" #include "ui/base/dragdrop/drag_drop_types.h" -#include "ui/base/events/event.h" -#include "ui/base/keycodes/keyboard_codes.h" #include "ui/compositor/layer.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/canvas.h" #include "ui/views/focus/view_storage.h" #include "ui/views/layout/fill_layout.h" @@ -20,6 +20,10 @@ #include "ui/views/widget/widget_delegate.h" #include "ui/views/widget/widget_deletion_observer.h" +#if defined(USE_AURA) +#include "ui/base/cursor/cursor.h" +#endif + namespace views { namespace internal { @@ -102,9 +106,8 @@ View* RootView::GetContentsView() { return child_count() > 0 ? child_at(0) : NULL; } -void RootView::NotifyNativeViewHierarchyChanged(bool attached, - gfx::NativeView native_view) { - PropagateNativeViewHierarchyChanged(attached, native_view, this); +void RootView::NotifyNativeViewHierarchyChanged() { + PropagateNativeViewHierarchyChanged(); } // Input ----------------------------------------------------------------------- @@ -123,8 +126,7 @@ void RootView::DispatchKeyEvent(ui::KeyEvent* event) { return; } - for (; v && v != this && !event->handled(); v = v->parent()) - DispatchEventToTarget(v, event); + DispatchKeyEventStartAt(v, event); } void RootView::DispatchScrollEvent(ui::ScrollEvent* event) { @@ -364,6 +366,11 @@ bool RootView::IsDrawn() const { return visible(); } +void RootView::Layout() { + View::Layout(); + widget_->OnRootViewLayout(); +} + const char* RootView::GetClassName() const { return kViewClassName; } @@ -637,10 +644,6 @@ void RootView::OnPaint(gfx::Canvas* canvas) { if (!layer() || !layer()->fills_bounds_opaquely()) canvas->DrawColor(SK_ColorBLACK, SkXfermode::kClear_Mode); - // TODO (pkotwicz): Remove this once we switch over to Aura desktop. - // This is needed so that we can set the background behind the RWHV when the - // RWHV is not visible. Not needed once there is a view between the RootView - // and RWHV. View::OnPaint(canvas); } @@ -699,6 +702,19 @@ void RootView::NotifyEnterExitOfDescendant(const ui::MouseEvent& event, } } + +void RootView::DispatchKeyEventStartAt(View* view, ui::KeyEvent* event) { + if (event->handled() || !view) + return; + + for (; view && view != this; view = view->parent()) { + DispatchEventToTarget(view, event); + // Do this check here rather than in the if as |view| may have been deleted. + if (event->handled()) + return; + } +} + bool RootView::CanDispatchToTarget(ui::EventTarget* target) { return event_dispatch_target_ == target; } diff --git a/chromium/ui/views/widget/root_view.h b/chromium/ui/views/widget/root_view.h index b89ab8fe8eb..6ab367bd992 100644 --- a/chromium/ui/views/widget/root_view.h +++ b/chromium/ui/views/widget/root_view.h @@ -8,7 +8,7 @@ #include <string> #include "base/memory/ref_counted.h" -#include "ui/base/events/event_dispatcher.h" +#include "ui/events/event_dispatcher.h" #include "ui/views/focus/focus_manager.h" #include "ui/views/focus/focus_search.h" #include "ui/views/view.h" @@ -16,6 +16,7 @@ namespace views { namespace test { +class RootViewTestHelper; class WidgetTest; } @@ -60,8 +61,7 @@ class VIEWS_EXPORT RootView : public View, View* GetContentsView(); // Called when parent of the host changed. - void NotifyNativeViewHierarchyChanged(bool attached, - gfx::NativeView native_view); + void NotifyNativeViewHierarchyChanged(); // Input --------------------------------------------------------------------- @@ -101,6 +101,7 @@ class VIEWS_EXPORT RootView : public View, virtual const Widget* GetWidget() const OVERRIDE; virtual Widget* GetWidget() OVERRIDE; virtual bool IsDrawn() const OVERRIDE; + virtual void Layout() OVERRIDE; virtual const char* GetClassName() const OVERRIDE; virtual void SchedulePaintInRect(const gfx::Rect& rect) OVERRIDE; virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; @@ -127,6 +128,7 @@ class VIEWS_EXPORT RootView : public View, private: friend class ::views::View; friend class ::views::Widget; + friend class ::views::test::RootViewTestHelper; friend class ::views::test::WidgetTest; // Input --------------------------------------------------------------------- @@ -153,6 +155,10 @@ class VIEWS_EXPORT RootView : public View, View* view, View* sibling); + // Dispatches the KeyEvent to |view| and ancestors until the event is + // handled. + void DispatchKeyEventStartAt(View* view, ui::KeyEvent* event); + // Overridden from ui::EventDispatcherDelegate: virtual bool CanDispatchToTarget(ui::EventTarget* target) OVERRIDE; diff --git a/chromium/ui/views/widget/root_view_test_helper.h b/chromium/ui/views/widget/root_view_test_helper.h new file mode 100644 index 00000000000..a26396730b2 --- /dev/null +++ b/chromium/ui/views/widget/root_view_test_helper.h @@ -0,0 +1,33 @@ +// 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. + +#ifndef UI_VIEWS_WIDGET_ROOT_VIEW_TEST_HELPER_H_ +#define UI_VIEWS_WIDGET_ROOT_VIEW_TEST_HELPER_H_ + +#include "ui/views/widget/root_view.h" + +namespace views { +namespace test { + +class RootViewTestHelper { + public: + explicit RootViewTestHelper(internal::RootView* root_view) + : root_view_(root_view) { + } + ~RootViewTestHelper() {} + + void DispatchKeyEventStartAt(View* view, ui::KeyEvent* event) { + root_view_->DispatchKeyEventStartAt(view, event); + } + + private: + internal::RootView* root_view_; + + DISALLOW_COPY_AND_ASSIGN(RootViewTestHelper); +}; + +} // namespace test +} // namespace views + +#endif // UI_VIEWS_WIDGET_ROOT_VIEW_TEST_HELPER_H_ diff --git a/chromium/ui/views/widget/root_view_unittest.cc b/chromium/ui/views/widget/root_view_unittest.cc new file mode 100644 index 00000000000..ebe20d65346 --- /dev/null +++ b/chromium/ui/views/widget/root_view_unittest.cc @@ -0,0 +1,55 @@ +// 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 "ui/views/test/views_test_base.h" +#include "ui/views/widget/root_view_test_helper.h" + +namespace views { +namespace test { + +typedef ViewsTestBase RootViewTest; + +class DeleteOnKeyEventView : public View { + public: + explicit DeleteOnKeyEventView(bool* set_on_key) : set_on_key_(set_on_key) {} + virtual ~DeleteOnKeyEventView() {} + + virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE { + *set_on_key_ = true; + delete this; + return true; + } + + private: + // Set to true in OnKeyPressed(). + bool* set_on_key_; + + DISALLOW_COPY_AND_ASSIGN(DeleteOnKeyEventView); +}; + +// Verifies deleting a View in OnKeyPressed() doesn't crash. +TEST_F(RootViewTest, DeleteViewDuringKeyEventDispatch) { + Widget widget; + Widget::InitParams init_params = + CreateParams(Widget::InitParams::TYPE_POPUP); + init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + widget.Init(init_params); + + bool got_key_event = false; + + View* content = new View; + widget.SetContentsView(content); + + View* child = new DeleteOnKeyEventView(&got_key_event); + content->AddChildView(child); + + ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_ESCAPE, 0, false); + RootViewTestHelper test_helper( + static_cast<internal::RootView*>(widget.GetRootView())); + test_helper.DispatchKeyEventStartAt(child, &key_event); + EXPECT_TRUE(got_key_event); +} + +} // namespace test +} // namespace views diff --git a/chromium/ui/views/widget/tooltip_manager.cc b/chromium/ui/views/widget/tooltip_manager.cc index bfcbf02b47d..7eb49787641 100644 --- a/chromium/ui/views/widget/tooltip_manager.cc +++ b/chromium/ui/views/widget/tooltip_manager.cc @@ -4,13 +4,13 @@ #include "ui/views/widget/tooltip_manager.h" +#include <algorithm> #include <vector> #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" -#include "ui/base/text/text_elider.h" - -namespace { +#include "ui/gfx/text_elider.h" +#include "ui/gfx/text_utils.h" // Maximum number of characters we allow in a tooltip. const size_t kMaxTooltipLength = 1024; @@ -18,8 +18,6 @@ const size_t kMaxTooltipLength = 1024; // Maximum number of lines we allow in the tooltip. const size_t kMaxLines = 6; -} // namespace - namespace views { // static @@ -48,13 +46,14 @@ void TooltipManager::TrimTooltipToFit(string16* text, *line_count = static_cast<int>(lines.size()); // Format each line to fit. - gfx::Font font = GetDefaultFont(); + const gfx::FontList& font_list = GetDefaultFontList(); string16 result; for (std::vector<string16>::iterator i = lines.begin(); i != lines.end(); ++i) { string16 elided_text = - ui::ElideText(*i, font, available_width, ui::ELIDE_AT_END); - *max_width = std::max(*max_width, font.GetStringWidth(elided_text)); + gfx::ElideText(*i, font_list, available_width, gfx::ELIDE_AT_END); + *max_width = std::max(*max_width, + gfx::GetStringWidth(elided_text, font_list)); if (!result.empty()) result.push_back('\n'); result.append(elided_text); diff --git a/chromium/ui/views/widget/tooltip_manager.h b/chromium/ui/views/widget/tooltip_manager.h index f8601dd6ae3..1228f5a509a 100644 --- a/chromium/ui/views/widget/tooltip_manager.h +++ b/chromium/ui/views/widget/tooltip_manager.h @@ -13,7 +13,7 @@ #include "ui/views/views_export.h" namespace gfx { -class Font; +class FontList; } // namespace gfx namespace views { @@ -30,7 +30,7 @@ class VIEWS_EXPORT TooltipManager { static int GetTooltipHeight(); // Returns the default font used by tooltips. - static gfx::Font GetDefaultFont(); + static const gfx::FontList& GetDefaultFontList(); // Returns the maximum width of the tooltip. |x| and |y| give the location // the tooltip is to be displayed on in screen coordinates. |context| is diff --git a/chromium/ui/views/widget/tooltip_manager_aura.cc b/chromium/ui/views/widget/tooltip_manager_aura.cc index f7a47613fc3..632946339a0 100644 --- a/chromium/ui/views/widget/tooltip_manager_aura.cc +++ b/chromium/ui/views/widget/tooltip_manager_aura.cc @@ -8,7 +8,6 @@ #include "ui/aura/client/tooltip_client.h" #include "ui/aura/root_window.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/font.h" #include "ui/gfx/rect.h" #include "ui/gfx/screen.h" #include "ui/views/widget/widget.h" @@ -23,8 +22,8 @@ int TooltipManager::GetTooltipHeight() { } // static -gfx::Font TooltipManager::GetDefaultFont() { - return ui::ResourceBundle::GetSharedInstance().GetFont( +const gfx::FontList& TooltipManager::GetDefaultFontList() { + return ui::ResourceBundle::GetSharedInstance().GetFontList( ui::ResourceBundle::BaseFont); } diff --git a/chromium/ui/views/widget/tooltip_manager_win.cc b/chromium/ui/views/widget/tooltip_manager_win.cc index fa0ad45d711..362ff33e886 100644 --- a/chromium/ui/views/widget/tooltip_manager_win.cc +++ b/chromium/ui/views/widget/tooltip_manager_win.cc @@ -16,11 +16,11 @@ #include "base/win/scoped_hdc.h" #include "base/win/scoped_select_object.h" #include "ui/base/l10n/l10n_util_win.h" -#include "ui/base/win/dpi.h" -#include "ui/base/win/hwnd_util.h" -#include "ui/base/win/scoped_set_map_mode.h" -#include "ui/gfx/font.h" +#include "ui/gfx/font_list.h" #include "ui/gfx/screen.h" +#include "ui/gfx/win/dpi.h" +#include "ui/gfx/win/hwnd_util.h" +#include "ui/gfx/win/scoped_set_map_mode.h" #include "ui/views/view.h" #include "ui/views/widget/monitor_win.h" #include "ui/views/widget/widget.h" @@ -52,11 +52,11 @@ static gfx::Font DetermineDefaultFont() { } // static -gfx::Font TooltipManager::GetDefaultFont() { - static gfx::Font* font = NULL; - if (!font) - font = new gfx::Font(DetermineDefaultFont()); - return *font; +const gfx::FontList& TooltipManager::GetDefaultFontList() { + static gfx::FontList* font_list = NULL; + if (!font_list) + font_list = new gfx::FontList(DetermineDefaultFont()); + return *font_list; } // static @@ -227,7 +227,7 @@ bool TooltipManagerWin::SetTooltipPosition(int text_x, int text_y) { // Calculate the bounds the tooltip will get. gfx::Point view_loc; View::ConvertPointToScreen(last_tooltip_view_, &view_loc); - view_loc = ui::win::DIPToScreenPoint(view_loc); + view_loc = gfx::win::DIPToScreenPoint(view_loc); RECT bounds = { view_loc.x() + text_x, view_loc.y() + text_y, view_loc.x() + text_x + tooltip_width_, @@ -257,7 +257,7 @@ int TooltipManagerWin::CalcTooltipHeight() { if (hfont != NULL) { base::win::ScopedGetDC dc(tooltip_hwnd_); base::win::ScopedSelectObject font(dc, hfont); - ui::ScopedSetMapMode mode(dc, MM_TEXT); + gfx::ScopedSetMapMode mode(dc, MM_TEXT); TEXTMETRIC font_metrics; GetTextMetrics(dc, &font_metrics); height = font_metrics.tmHeight; @@ -301,14 +301,14 @@ void TooltipManagerWin::UpdateTooltip(const gfx::Point& mouse_pos) { void TooltipManagerWin::OnMouse(UINT u_msg, WPARAM w_param, LPARAM l_param) { gfx::Point mouse_pos_in_pixels(l_param); - gfx::Point mouse_pos = ui::win::ScreenToDIPPoint(mouse_pos_in_pixels); + gfx::Point mouse_pos = gfx::win::ScreenToDIPPoint(mouse_pos_in_pixels); if (u_msg >= WM_NCMOUSEMOVE && u_msg <= WM_NCXBUTTONDBLCLK) { // NC message coordinates are in screen coordinates. POINT temp = mouse_pos_in_pixels.ToPOINT(); ::MapWindowPoints(HWND_DESKTOP, GetParent(), &temp, 1); mouse_pos_in_pixels.SetPoint(temp.x, temp.y); - mouse_pos = ui::win::ScreenToDIPPoint(mouse_pos_in_pixels); + mouse_pos = gfx::win::ScreenToDIPPoint(mouse_pos_in_pixels); } if (u_msg != WM_MOUSEMOVE || last_mouse_pos_ != mouse_pos) { diff --git a/chromium/ui/views/widget/widget.cc b/chromium/ui/views/widget/widget.cc index e97c950261b..168cfdfa163 100644 --- a/chromium/ui/views/widget/widget.cc +++ b/chromium/ui/views/widget/widget.cc @@ -9,13 +9,14 @@ #include "base/message_loop/message_loop.h" #include "base/strings/utf_string_conversions.h" #include "ui/base/default_theme_provider.h" -#include "ui/base/events/event.h" #include "ui/base/hit_test.h" #include "ui/base/l10n/l10n_font_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/compositor/compositor.h" #include "ui/compositor/layer.h" +#include "ui/events/event.h" #include "ui/gfx/screen.h" +#include "ui/views/controls/menu/menu_controller.h" #include "ui/views/focus/focus_manager.h" #include "ui/views/focus/focus_manager_factory.h" #include "ui/views/focus/view_storage.h" @@ -29,9 +30,10 @@ #include "ui/views/widget/widget_deletion_observer.h" #include "ui/views/widget/widget_observer.h" #include "ui/views/window/custom_frame_view.h" +#include "ui/views/window/dialog_delegate.h" -#if !defined(OS_MACOSX) -#include "ui/views/controls/menu/menu_controller.h" +#if defined(USE_AURA) +#include "ui/base/cursor/cursor.h" #endif namespace views { @@ -85,10 +87,15 @@ class DefaultWidgetDelegate : public WidgetDelegate { virtual const Widget* GetWidget() const OVERRIDE { return widget_; } - virtual bool CanActivate() const OVERRIDE { return can_activate_; } + virtual bool ShouldAdvanceFocusToTopLevelWidget() const OVERRIDE { + // In most situations where a Widget is used without a delegate the Widget + // is used as a container, so that we want focus to advance to the top-level + // widget. A good example of this is the find bar. + return true; + } private: Widget* widget_; @@ -172,6 +179,7 @@ Widget::Widget() is_mouse_button_pressed_(false), is_touch_down_(false), last_mouse_event_was_move_(false), + auto_release_capture_(true), root_layers_dirty_(false), movement_disabled_(false) { } @@ -243,6 +251,30 @@ Widget* Widget::CreateWindowWithContextAndBounds(WidgetDelegate* delegate, } // static +Widget* Widget::CreateWindowAsFramelessChild(WidgetDelegate* widget_delegate, + gfx::NativeView parent, + gfx::NativeView new_style_parent) { + views::Widget* widget = new views::Widget; + + views::Widget::InitParams params; + params.delegate = widget_delegate; + params.child = true; + if (views::DialogDelegate::UseNewStyle()) { + params.parent = new_style_parent; + params.remove_standard_frame = true; +#if defined(USE_AURA) + params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; +#endif + } else { + params.parent = parent; + } + + widget->Init(params); + + return widget; +} + +// static Widget* Widget::GetWidgetForNativeView(gfx::NativeView native_view) { internal::NativeWidgetPrivate* native_widget = internal::NativeWidgetPrivate::GetNativeWidgetForNativeView(native_view); @@ -272,6 +304,12 @@ void Widget::GetAllChildWidgets(gfx::NativeView native_view, } // static +void Widget::GetAllOwnedWidgets(gfx::NativeView native_view, + Widgets* owned) { + internal::NativeWidgetPrivate::GetAllOwnedWidgets(native_view, owned); +} + +// static void Widget::ReparentNativeView(gfx::NativeView native_view, gfx::NativeView new_parent) { internal::NativeWidgetPrivate::ReparentNativeView(native_view, new_parent); @@ -402,16 +440,16 @@ void Widget::ViewHierarchyChanged( } } -void Widget::NotifyNativeViewHierarchyChanged(bool attached, - gfx::NativeView native_view) { - if (!attached) { - FocusManager* focus_manager = GetFocusManager(); - // We are being removed from a window hierarchy. Treat this as - // the root_view_ being removed. - if (focus_manager) - focus_manager->ViewRemoved(root_view_.get()); - } - root_view_->NotifyNativeViewHierarchyChanged(attached, native_view); +void Widget::NotifyNativeViewHierarchyWillChange() { + FocusManager* focus_manager = GetFocusManager(); + // We are being removed from a window hierarchy. Treat this as + // the root_view_ being removed. + if (focus_manager) + focus_manager->ViewRemoved(root_view_.get()); +} + +void Widget::NotifyNativeViewHierarchyChanged() { + root_view_->NotifyNativeViewHierarchyChanged(); } // Converted methods (see header) ---------------------------------------------- @@ -561,17 +599,6 @@ bool Widget::IsClosed() const { void Widget::Show() { TRACE_EVENT0("views", "Widget::Show"); if (non_client_view_) { -#if defined(OS_MACOSX) - // On the Mac the FullScreenBookmarkBar test is different then for any other - // OS. Since the new maximize logic from ash does not apply to the mac, we - // continue to ignore the fullscreen mode here. - if (saved_show_state_ == ui::SHOW_STATE_MAXIMIZED && - !initial_restored_bounds_.IsEmpty()) { - native_widget_->ShowMaximizedWithBounds(initial_restored_bounds_); - } else { - native_widget_->ShowWithWindowState(saved_show_state_); - } -#else // While initializing, the kiosk mode will go to full screen before the // widget gets shown. In that case we stay in full screen mode, regardless // of the |saved_show_state_| member. @@ -583,7 +610,6 @@ void Widget::Show() { native_widget_->ShowWithWindowState( IsFullscreen() ? ui::SHOW_STATE_FULLSCREEN : saved_show_state_); } -#endif // |saved_show_state_| only applies the first time the window is shown. // If we don't reset the value the window may be shown maximized every time // it is subsequently shown after being hidden. @@ -923,10 +949,6 @@ bool Widget::SetInitialFocus() { return !!v; } -View* Widget::GetChildViewParent() { - return GetContentsView() ? GetContentsView() : GetRootView(); -} - gfx::Rect Widget::GetWorkAreaBoundsInScreen() const { return native_widget_->GetWorkAreaBoundsInScreen(); } @@ -940,6 +962,10 @@ void Widget::SynthesizeMouseMoveEvent() { root_view_->OnMouseMoved(mouse_event); } +void Widget::OnRootViewLayout() { + native_widget_->OnRootViewLayout(); +} + void Widget::OnOwnerClosing() { } @@ -987,6 +1013,11 @@ void Widget::OnNativeBlur(gfx::NativeView new_focused_view) { new_focused_view); } +void Widget::OnNativeWidgetVisibilityChanging(bool visible) { + FOR_EACH_OBSERVER(WidgetObserver, observers_, + OnWidgetVisibilityChanging(this, visible)); +} + void Widget::OnNativeWidgetVisibilityChanged(bool visible) { View* root = GetRootView(); if (root) @@ -1098,9 +1129,6 @@ void Widget::OnKeyEvent(ui::KeyEvent* event) { } void Widget::OnMouseEvent(ui::MouseEvent* event) { - if (!IsMouseEventsEnabled()) - return; - View* root_view = GetRootView(); switch (event->type()) { case ui::ET_MOUSE_PRESSED: { @@ -1134,10 +1162,8 @@ void Widget::OnMouseEvent(ui::MouseEvent* event) { last_mouse_event_was_move_ = false; is_mouse_button_pressed_ = false; // Release capture first, to avoid confusion if OnMouseReleased blocks. - if (native_widget_->HasCapture() && - ShouldReleaseCaptureOnMouseReleased()) { + if (auto_release_capture_ && native_widget_->HasCapture()) native_widget_->ReleaseCapture(); - } if (root_view) root_view->OnMouseReleased(*event); if ((event->flags() & ui::EF_IS_NON_CLIENT) == 0) @@ -1205,7 +1231,7 @@ void Widget::OnGestureEvent(ui::GestureEvent* event) { case ui::ET_GESTURE_END: if (event->details().touch_points() == 1) { is_touch_down_ = false; - if (ShouldReleaseCaptureOnMouseReleased()) + if (auto_release_capture_) ReleaseCapture(); } break; @@ -1288,10 +1314,6 @@ void Widget::DestroyRootView() { //////////////////////////////////////////////////////////////////////////////// // Widget, private: -bool Widget::ShouldReleaseCaptureOnMouseReleased() const { - return true; -} - void Widget::SetInactiveRenderingDisabled(bool value) { if (value == disable_inactive_rendering_) return; diff --git a/chromium/ui/views/widget/widget.h b/chromium/ui/views/widget/widget.h index f020a0c7de1..1600f946921 100644 --- a/chromium/ui/views/widget/widget.h +++ b/chromium/ui/views/widget/widget.h @@ -156,7 +156,6 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, InitParams(); explicit InitParams(Type type); - // Will return the first of the following that isn't NULL: the native view, // |parent|, |context|. gfx::NativeView GetContext() const; @@ -177,9 +176,9 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, Ownership ownership; bool mirror_origin_in_rtl; bool has_dropshadow; - // Only used by NativeWidgetWin. Specifies that the system default caption - // and icon should not be rendered, and that the client area should be - // equivalent to the window area. + // Only used by Windows. Specifies that the system default caption and icon + // should not be rendered, and that the client area should be equivalent to + // the window area. bool remove_standard_frame; // Only used by ShellWindow on Windows. Specifies that the default icon of // packaged app should be the system default icon. @@ -217,6 +216,11 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, // where it wants your window placed.) NULL is not allowed if you are using // aura. gfx::NativeView context; + // Only used by X11, for root level windows. Specifies the res_name and + // res_class fields, respectively, of the WM_CLASS window property. Controls + // window grouping and desktop file matching in Linux window managers. + std::string wm_class_name; + std::string wm_class_class; }; Widget(); @@ -248,6 +252,14 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, gfx::NativeView context, const gfx::Rect& bounds); + // Creates an undecorated child window Widget. |new_style_parent| is the + // parent to use for new style dialogs, |parent| for currently-styled dialogs. + // + // TODO(wittman): use a single parent parameter once we move fully to + // new-style dialogs. + static Widget* CreateWindowAsFramelessChild(WidgetDelegate* widget_delegate, + gfx::NativeView parent, + gfx::NativeView new_style_parent); // Enumerates all windows pertaining to us and notifies their // view hierarchies that the locale has changed. @@ -284,6 +296,10 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, static void GetAllChildWidgets(gfx::NativeView native_view, Widgets* children); + // Returns all non-child Widgets owned by |native_view|. + static void GetAllOwnedWidgets(gfx::NativeView native_view, + Widgets* owned); + // Re-parent a NativeView and notify all Widgets in |native_view|'s hierarchy // of the change. static void ReparentNativeView(gfx::NativeView native_view, @@ -324,9 +340,13 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, // Forwarded from the RootView so that the widget can do any cleanup. void ViewHierarchyChanged(const View::ViewHierarchyChangedDetails& details); - // Performs any necessary cleanup and forwards to RootView. - void NotifyNativeViewHierarchyChanged(bool attached, - gfx::NativeView native_view); + // Called right before changing the widget's parent NativeView to do any + // cleanup. + void NotifyNativeViewHierarchyWillChange(); + + // Called after changing the widget's parent NativeView. Notifies the RootView + // about the change. + void NotifyNativeViewHierarchyChanged(); // Returns the top level widget in a hierarchy (see is_top_level() for // the definition of top level widget.) Will return NULL if called @@ -615,7 +635,9 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, } // Sets capture to the specified view. This makes it so that all mouse, touch - // and gesture events go to |view|. + // and gesture events go to |view|. If |view| is NULL, the widget still + // obtains event capture, but the events will go to the view they'd normally + // go to. void SetCapture(View* view); // Releases capture. @@ -624,6 +646,10 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, // Returns true if the widget has capture. bool HasCapture(); + void set_auto_release_capture(bool auto_release_capture) { + auto_release_capture_ = auto_release_capture; + } + // Invoked when the tooltip text changes for the specified views. void TooltipTextChanged(View* view); @@ -637,11 +663,6 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, focus_on_creation_ = focus_on_creation; } - // Returns a View* that any child Widgets backed by NativeWidgetViews - // are added to. The default implementation returns the contents view - // if it exists and the root view otherwise. - virtual View* GetChildViewParent(); - // True if the widget is considered top level widget. Top level widget // is a widget of TYPE_WINDOW, TYPE_PANEL, TYPE_WINDOW_FRAMELESS, BUBBLE, // POPUP or MENU, and has a focus manager and input method object associated @@ -659,6 +680,10 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, // mouse location to refresh hovering status in the widget. void SynthesizeMouseMoveEvent(); + // Called by our RootView after it has performed a Layout. Used to forward + // window sizing information to the window server on some platforms. + void OnRootViewLayout(); + // Notification that our owner is closing. // NOTE: this is not invoked for aura as it's currently not needed there. // Under aura menus close by way of activation getting reset when the owner @@ -674,6 +699,7 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, virtual void OnNativeWidgetActivationChanged(bool active) OVERRIDE; virtual void OnNativeFocus(gfx::NativeView old_focused_view) OVERRIDE; virtual void OnNativeBlur(gfx::NativeView new_focused_view) OVERRIDE; + virtual void OnNativeWidgetVisibilityChanging(bool visible) OVERRIDE; virtual void OnNativeWidgetVisibilityChanged(bool visible) OVERRIDE; virtual void OnNativeWidgetCreated(bool desktop_widget) OVERRIDE; virtual void OnNativeWidgetDestroying() OVERRIDE; @@ -720,11 +746,8 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, void DestroyRootView(); private: + friend class ComboboxTest; friend class NativeTextfieldViewsTest; - friend class NativeComboboxViewsTest; - - // Returns whether capture should be released on mouse release. - virtual bool ShouldReleaseCaptureOnMouseReleased() const; // Sets the value of |disable_inactive_rendering_|. If the value changes, // both the NonClientView and WidgetDelegate are notified. @@ -757,8 +780,8 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, ObserverList<WidgetObserver> observers_; - // Non-owned pointer to the Widget's delegate. May be NULL if no delegate is - // being used. + // Non-owned pointer to the Widget's delegate. If a NULL delegate is supplied + // to Init() a default WidgetDelegate is created. WidgetDelegate* widget_delegate_; // The root of the View hierarchy attached to this window. @@ -840,6 +863,10 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, bool last_mouse_event_was_move_; gfx::Point last_mouse_event_position_; + // True if event capture should be released on a mouse up event. Default is + // true. + bool auto_release_capture_; + // See description in GetRootLayers(). std::vector<ui::Layer*> root_layers_; diff --git a/chromium/ui/views/widget/widget_delegate.cc b/chromium/ui/views/widget/widget_delegate.cc index dcb7c361030..37816da4eef 100644 --- a/chromium/ui/views/widget/widget_delegate.cc +++ b/chromium/ui/views/widget/widget_delegate.cc @@ -162,6 +162,10 @@ void WidgetDelegate::GetWidgetHitTestMask(gfx::Path* mask) const { DCHECK(mask); } +bool WidgetDelegate::ShouldAdvanceFocusToTopLevelWidget() const { + return false; +} + bool WidgetDelegate::ShouldDescendIntoChildForEventHandling( gfx::NativeView child, const gfx::Point& location) { diff --git a/chromium/ui/views/widget/widget_delegate.h b/chromium/ui/views/widget/widget_delegate.h index f465ffb3bc1..4466e52cfa2 100644 --- a/chromium/ui/views/widget/widget_delegate.h +++ b/chromium/ui/views/widget/widget_delegate.h @@ -159,6 +159,11 @@ class VIEWS_EXPORT WidgetDelegate { // Provides the hit-test mask if HasHitTestMask above returns true. virtual void GetWidgetHitTestMask(gfx::Path* mask) const; + // Returns true if focus should advance to the top level widget when + // tab/shift-tab is hit and on the last/first focusable view. Default returns + // false, which means tab/shift-tab never advance to the top level Widget. + virtual bool ShouldAdvanceFocusToTopLevelWidget() const; + // Returns true if event handling should descend into |child|. // |location| is in terms of the Window. virtual bool ShouldDescendIntoChildForEventHandling( diff --git a/chromium/ui/views/widget/widget_interactive_uitest.cc b/chromium/ui/views/widget/widget_interactive_uitest.cc new file mode 100644 index 00000000000..b05a0bc8be6 --- /dev/null +++ b/chromium/ui/views/widget/widget_interactive_uitest.cc @@ -0,0 +1,445 @@ +// Copyright (c) 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 "base/basictypes.h" +#include "base/bind.h" +#include "base/run_loop.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/views/test/widget_test.h" +#include "ui/views/widget/widget.h" + +#if defined(USE_AURA) +#include "ui/aura/client/activation_client.h" +#include "ui/aura/env.h" +#include "ui/aura/root_window.h" +#if !defined(OS_CHROMEOS) +#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" +#endif +#endif + +namespace views { +namespace test { + +namespace { + +// A View that closes the Widget and exits the current message-loop when it +// receives a mouse-release event. +class ExitLoopOnRelease : public View { + public: + ExitLoopOnRelease() {} + virtual ~ExitLoopOnRelease() {} + + private: + // Overridden from View: + virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE { + GetWidget()->Close(); + base::MessageLoop::current()->QuitNow(); + } + + DISALLOW_COPY_AND_ASSIGN(ExitLoopOnRelease); +}; + +// A view that does a capture on gesture-begin events. +class GestureCaptureView : public View { + public: + GestureCaptureView() {} + virtual ~GestureCaptureView() {} + + private: + // Overridden from View: + virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { + if (event->type() == ui::ET_GESTURE_BEGIN) { + GetWidget()->SetCapture(this); + event->StopPropagation(); + } + } + + DISALLOW_COPY_AND_ASSIGN(GestureCaptureView); +}; + +// A view that always processes all mouse events. +class MouseView : public View { + public: + MouseView() + : View(), + entered_(0), + exited_(0), + pressed_(0) { + } + virtual ~MouseView() {} + + virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE { + pressed_++; + return true; + } + + virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE { + entered_++; + } + + virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE { + exited_++; + } + + // Return the number of OnMouseEntered calls and reset the counter. + int EnteredCalls() { + int i = entered_; + entered_ = 0; + return i; + } + + // Return the number of OnMouseExited calls and reset the counter. + int ExitedCalls() { + int i = exited_; + exited_ = 0; + return i; + } + + int pressed() const { return pressed_; } + + private: + int entered_; + int exited_; + + int pressed_; + + DISALLOW_COPY_AND_ASSIGN(MouseView); +}; + +// A View that shows a different widget, sets capture on that widget, and +// initiates a nested message-loop when it receives a mouse-press event. +class NestedLoopCaptureView : public View { + public: + explicit NestedLoopCaptureView(Widget* widget) : widget_(widget) {} + virtual ~NestedLoopCaptureView() {} + + private: + // Overridden from View: + virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE { + // Start a nested loop. + widget_->Show(); + widget_->SetCapture(widget_->GetContentsView()); + EXPECT_TRUE(widget_->HasCapture()); + + base::MessageLoopForUI* loop = base::MessageLoopForUI::current(); + base::MessageLoop::ScopedNestableTaskAllower allow(loop); + + base::RunLoop run_loop; +#if defined(USE_AURA) + run_loop.set_dispatcher(aura::Env::GetInstance()->GetDispatcher()); +#endif + run_loop.Run(); + return true; + } + + Widget* widget_; + + DISALLOW_COPY_AND_ASSIGN(NestedLoopCaptureView); +}; + +} // namespace + +#if defined(OS_WIN) && defined(USE_AURA) +// Tests whether activation and focus change works correctly in Windows AURA. +// We test the following:- +// 1. If the active aura window is correctly set when a top level widget is +// created. +// 2. If the active aura window in widget 1 created above, is set to NULL when +// another top level widget is created and focused. +// 3. On focusing the native platform window for widget 1, the active aura +// window for widget 1 should be set and that for widget 2 should reset. +// TODO(ananta) +// Discuss with erg on how to write this test for linux x11 aura. +TEST_F(WidgetTest, DesktopNativeWidgetAuraActivationAndFocusTest) { + // Create widget 1 and expect the active window to be its window. + View* contents_view1 = new View; + contents_view1->set_focusable(true); + Widget widget1; + Widget::InitParams init_params = + CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); + init_params.bounds = gfx::Rect(0, 0, 200, 200); + init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + init_params.native_widget = new DesktopNativeWidgetAura(&widget1); + widget1.Init(init_params); + widget1.SetContentsView(contents_view1); + widget1.Show(); + aura::RootWindow* root_window1= widget1.GetNativeView()->GetRootWindow(); + contents_view1->RequestFocus(); + + EXPECT_TRUE(root_window1 != NULL); + aura::client::ActivationClient* activation_client1 = + aura::client::GetActivationClient(root_window1); + EXPECT_TRUE(activation_client1 != NULL); + EXPECT_EQ(activation_client1->GetActiveWindow(), widget1.GetNativeView()); + + // Create widget 2 and expect the active window to be its window. + View* contents_view2 = new View; + Widget widget2; + Widget::InitParams init_params2 = + CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); + init_params2.bounds = gfx::Rect(0, 0, 200, 200); + init_params2.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + init_params2.native_widget = new DesktopNativeWidgetAura(&widget2); + widget2.Init(init_params2); + widget2.SetContentsView(contents_view2); + widget2.Show(); + aura::RootWindow* root_window2 = widget2.GetNativeView()->GetRootWindow(); + contents_view2->RequestFocus(); + ::SetActiveWindow(root_window2->GetAcceleratedWidget()); + + aura::client::ActivationClient* activation_client2 = + aura::client::GetActivationClient(root_window2); + EXPECT_TRUE(activation_client2 != NULL); + EXPECT_EQ(activation_client2->GetActiveWindow(), widget2.GetNativeView()); + EXPECT_EQ(activation_client1->GetActiveWindow(), + reinterpret_cast<aura::Window*>(NULL)); + + // Now set focus back to widget 1 and expect the active window to be its + // window. + contents_view1->RequestFocus(); + ::SetActiveWindow(root_window1->GetAcceleratedWidget()); + EXPECT_EQ(activation_client2->GetActiveWindow(), + reinterpret_cast<aura::Window*>(NULL)); + EXPECT_EQ(activation_client1->GetActiveWindow(), widget1.GetNativeView()); +} +#endif + +TEST_F(WidgetTest, CaptureAutoReset) { + Widget* toplevel = CreateTopLevelFramelessPlatformWidget(); + View* container = new View; + toplevel->SetContentsView(container); + + EXPECT_FALSE(toplevel->HasCapture()); + toplevel->SetCapture(NULL); + EXPECT_TRUE(toplevel->HasCapture()); + + // By default, mouse release removes capture. + gfx::Point click_location(45, 15); + ui::MouseEvent release(ui::ET_MOUSE_RELEASED, click_location, click_location, + ui::EF_LEFT_MOUSE_BUTTON); + toplevel->OnMouseEvent(&release); + EXPECT_FALSE(toplevel->HasCapture()); + + // Now a mouse release shouldn't remove capture. + toplevel->set_auto_release_capture(false); + toplevel->SetCapture(NULL); + EXPECT_TRUE(toplevel->HasCapture()); + toplevel->OnMouseEvent(&release); + EXPECT_TRUE(toplevel->HasCapture()); + toplevel->ReleaseCapture(); + EXPECT_FALSE(toplevel->HasCapture()); + + toplevel->Close(); + RunPendingMessages(); +} + +TEST_F(WidgetTest, ResetCaptureOnGestureEnd) { + Widget* toplevel = CreateTopLevelFramelessPlatformWidget(); + View* container = new View; + toplevel->SetContentsView(container); + + View* gesture = new GestureCaptureView; + gesture->SetBounds(0, 0, 30, 30); + container->AddChildView(gesture); + + MouseView* mouse = new MouseView; + mouse->SetBounds(30, 0, 30, 30); + container->AddChildView(mouse); + + toplevel->SetSize(gfx::Size(100, 100)); + toplevel->Show(); + + // Start a gesture on |gesture|. + ui::GestureEvent begin(ui::ET_GESTURE_BEGIN, + 15, 15, 0, base::TimeDelta(), + ui::GestureEventDetails(ui::ET_GESTURE_BEGIN, 0, 0), 1); + ui::GestureEvent end(ui::ET_GESTURE_END, + 15, 15, 0, base::TimeDelta(), + ui::GestureEventDetails(ui::ET_GESTURE_END, 0, 0), 1); + toplevel->OnGestureEvent(&begin); + + // Now try to click on |mouse|. Since |gesture| will have capture, |mouse| + // will not receive the event. + gfx::Point click_location(45, 15); + + ui::MouseEvent press(ui::ET_MOUSE_PRESSED, click_location, click_location, + ui::EF_LEFT_MOUSE_BUTTON); + ui::MouseEvent release(ui::ET_MOUSE_RELEASED, click_location, click_location, + ui::EF_LEFT_MOUSE_BUTTON); + + EXPECT_TRUE(toplevel->HasCapture()); + + toplevel->OnMouseEvent(&press); + toplevel->OnMouseEvent(&release); + EXPECT_EQ(0, mouse->pressed()); + + EXPECT_FALSE(toplevel->HasCapture()); + + // The end of the gesture should release the capture, and pressing on |mouse| + // should now reach |mouse|. + toplevel->OnGestureEvent(&end); + toplevel->OnMouseEvent(&press); + toplevel->OnMouseEvent(&release); + EXPECT_EQ(1, mouse->pressed()); + + toplevel->Close(); + RunPendingMessages(); +} + +// Checks that if a mouse-press triggers a capture on a different widget (which +// consumes the mouse-release event), then the target of the press does not have +// capture. +// Fails on chromium.webkit Windows bot, see crbug.com/264872. +#if defined(OS_WIN) +#define MAYBE_DisableCaptureWidgetFromMousePress\ + DISABLED_CaptureWidgetFromMousePress +#else +#define MAYBE_DisableCaptureWidgetFromMousePress\ + CaptureWidgetFromMousePress +#endif +TEST_F(WidgetTest, MAYBE_DisableCaptureWidgetFromMousePress) { + // The test creates two widgets: |first| and |second|. + // The View in |first| makes |second| visible, sets capture on it, and starts + // a nested loop (like a menu does). The View in |second| terminates the + // nested loop and closes the widget. + // The test sends a mouse-press event to |first|, and posts a task to send a + // release event to |second|, to make sure that the release event is + // dispatched after the nested loop starts. + + Widget* first = CreateTopLevelFramelessPlatformWidget(); + Widget* second = CreateTopLevelFramelessPlatformWidget(); + + View* container = new NestedLoopCaptureView(second); + first->SetContentsView(container); + + second->SetContentsView(new ExitLoopOnRelease()); + + first->SetSize(gfx::Size(100, 100)); + first->Show(); + + gfx::Point location(20, 20); + base::MessageLoop::current()->PostTask(FROM_HERE, + base::Bind(&Widget::OnMouseEvent, + base::Unretained(second), + base::Owned(new ui::MouseEvent(ui::ET_MOUSE_RELEASED, + location, + location, + ui::EF_LEFT_MOUSE_BUTTON)))); + ui::MouseEvent press(ui::ET_MOUSE_PRESSED, location, location, + ui::EF_LEFT_MOUSE_BUTTON); + first->OnMouseEvent(&press); + EXPECT_FALSE(first->HasCapture()); + first->Close(); + RunPendingMessages(); +} + +// Tests some grab/ungrab events. +// TODO(estade): can this be enabled now that this is an interactive ui test? +TEST_F(WidgetTest, DISABLED_GrabUngrab) { + Widget* toplevel = CreateTopLevelPlatformWidget(); + Widget* child1 = CreateChildNativeWidgetWithParent(toplevel); + Widget* child2 = CreateChildNativeWidgetWithParent(toplevel); + + toplevel->SetBounds(gfx::Rect(0, 0, 500, 500)); + + child1->SetBounds(gfx::Rect(10, 10, 300, 300)); + View* view = new MouseView(); + view->SetBounds(0, 0, 300, 300); + child1->GetRootView()->AddChildView(view); + + child2->SetBounds(gfx::Rect(200, 10, 200, 200)); + view = new MouseView(); + view->SetBounds(0, 0, 200, 200); + child2->GetRootView()->AddChildView(view); + + toplevel->Show(); + RunPendingMessages(); + + // Click on child1 + gfx::Point p1(45, 45); + ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, p1, p1, + ui::EF_LEFT_MOUSE_BUTTON); + toplevel->OnMouseEvent(&pressed); + + EXPECT_TRUE(toplevel->HasCapture()); + EXPECT_TRUE(child1->HasCapture()); + EXPECT_FALSE(child2->HasCapture()); + + ui::MouseEvent released(ui::ET_MOUSE_RELEASED, p1, p1, + ui::EF_LEFT_MOUSE_BUTTON); + toplevel->OnMouseEvent(&released); + + EXPECT_FALSE(toplevel->HasCapture()); + EXPECT_FALSE(child1->HasCapture()); + EXPECT_FALSE(child2->HasCapture()); + + RunPendingMessages(); + + // Click on child2 + gfx::Point p2(315, 45); + ui::MouseEvent pressed2(ui::ET_MOUSE_PRESSED, p2, p2, + ui::EF_LEFT_MOUSE_BUTTON); + toplevel->OnMouseEvent(&pressed2); + EXPECT_TRUE(pressed2.handled()); + EXPECT_TRUE(toplevel->HasCapture()); + EXPECT_TRUE(child2->HasCapture()); + EXPECT_FALSE(child1->HasCapture()); + + ui::MouseEvent released2(ui::ET_MOUSE_RELEASED, p2, p2, + ui::EF_LEFT_MOUSE_BUTTON); + toplevel->OnMouseEvent(&released2); + EXPECT_FALSE(toplevel->HasCapture()); + EXPECT_FALSE(child1->HasCapture()); + EXPECT_FALSE(child2->HasCapture()); + + toplevel->CloseNow(); +} + +// Tests mouse move outside of the window into the "resize controller" and back +// will still generate an OnMouseEntered and OnMouseExited event.. +TEST_F(WidgetTest, CheckResizeControllerEvents) { + Widget* toplevel = CreateTopLevelPlatformWidget(); + + toplevel->SetBounds(gfx::Rect(0, 0, 100, 100)); + + MouseView* view = new MouseView(); + view->SetBounds(90, 90, 10, 10); + toplevel->GetRootView()->AddChildView(view); + + toplevel->Show(); + RunPendingMessages(); + + // Move to an outside position. + gfx::Point p1(200, 200); + ui::MouseEvent moved_out(ui::ET_MOUSE_MOVED, p1, p1, ui::EF_NONE); + toplevel->OnMouseEvent(&moved_out); + EXPECT_EQ(0, view->EnteredCalls()); + EXPECT_EQ(0, view->ExitedCalls()); + + // Move onto the active view. + gfx::Point p2(95, 95); + ui::MouseEvent moved_over(ui::ET_MOUSE_MOVED, p2, p2, ui::EF_NONE); + toplevel->OnMouseEvent(&moved_over); + EXPECT_EQ(1, view->EnteredCalls()); + EXPECT_EQ(0, view->ExitedCalls()); + + // Move onto the outer resizing border. + gfx::Point p3(102, 95); + ui::MouseEvent moved_resizer(ui::ET_MOUSE_MOVED, p3, p3, ui::EF_NONE); + toplevel->OnMouseEvent(&moved_resizer); + EXPECT_EQ(0, view->EnteredCalls()); + EXPECT_EQ(1, view->ExitedCalls()); + + // Move onto the view again. + toplevel->OnMouseEvent(&moved_over); + EXPECT_EQ(1, view->EnteredCalls()); + EXPECT_EQ(0, view->ExitedCalls()); + + RunPendingMessages(); + + toplevel->CloseNow(); +} + +} // namespace test +} // namespace views diff --git a/chromium/ui/views/widget/widget_observer.h b/chromium/ui/views/widget/widget_observer.h index e156ef80c88..fc13afae682 100644 --- a/chromium/ui/views/widget/widget_observer.h +++ b/chromium/ui/views/widget/widget_observer.h @@ -36,6 +36,8 @@ class VIEWS_EXPORT WidgetObserver { // widget has been destroyed. virtual void OnWidgetDestroyed(Widget* widget) {} + virtual void OnWidgetVisibilityChanging(Widget* widget, bool visible) {} + virtual void OnWidgetVisibilityChanged(Widget* widget, bool visible) {} virtual void OnWidgetActivationChanged(Widget* widget, bool active) {} diff --git a/chromium/ui/views/widget/widget_unittest.cc b/chromium/ui/views/widget/widget_unittest.cc index 1153538b8d8..1c8a7a2de21 100644 --- a/chromium/ui/views/widget/widget_unittest.cc +++ b/chromium/ui/views/widget/widget_unittest.cc @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <algorithm> +#include <set> + #include "base/basictypes.h" #include "base/bind.h" #include "base/memory/scoped_ptr.h" @@ -9,13 +12,13 @@ #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/events/event_utils.h" +#include "ui/events/event_utils.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/point.h" #include "ui/views/bubble/bubble_delegate.h" #include "ui/views/controls/textfield/textfield.h" #include "ui/views/test/test_views_delegate.h" -#include "ui/views/test/views_test_base.h" +#include "ui/views/test/widget_test.h" #include "ui/views/views_delegate.h" #include "ui/views/widget/native_widget_delegate.h" #include "ui/views/widget/root_view.h" @@ -23,9 +26,7 @@ #if defined(USE_AURA) #include "ui/aura/client/aura_constants.h" -#include "ui/aura/env.h" #include "ui/aura/root_window.h" -#include "ui/aura/test/test_cursor_client.h" #include "ui/aura/test/test_window_delegate.h" #include "ui/aura/window.h" #include "ui/views/widget/native_widget_aura.h" @@ -39,99 +40,6 @@ namespace views { namespace test { -// A generic typedef to pick up relevant NativeWidget implementations. -#if defined(USE_AURA) -typedef NativeWidgetAura NativeWidgetPlatform; -#elif defined(OS_WIN) -typedef NativeWidgetWin NativeWidgetPlatform; -#endif - -// A widget that assumes mouse capture always works. It won't on Aura in -// testing, so we mock it. -#if defined(USE_AURA) -class NativeWidgetCapture : public NativeWidgetPlatform { - public: - explicit NativeWidgetCapture(internal::NativeWidgetDelegate* delegate) - : NativeWidgetPlatform(delegate), - mouse_capture_(false) {} - virtual ~NativeWidgetCapture() {} - - virtual void SetCapture() OVERRIDE { - mouse_capture_ = true; - } - virtual void ReleaseCapture() OVERRIDE { - if (mouse_capture_) - delegate()->OnMouseCaptureLost(); - mouse_capture_ = false; - } - virtual bool HasCapture() const OVERRIDE { - return mouse_capture_; - } - - private: - bool mouse_capture_; - - DISALLOW_COPY_AND_ASSIGN(NativeWidgetCapture); -}; -#endif - -// A typedef that inserts our mock-capture NativeWidget implementation for -// relevant platforms. -#if defined(USE_AURA) -typedef NativeWidgetCapture NativeWidgetPlatformForTest; -#elif defined(OS_WIN) -typedef NativeWidgetWin NativeWidgetPlatformForTest; -#endif - -// A view that always processes all mouse events. -class MouseView : public View { - public: - MouseView() - : View(), - entered_(0), - exited_(0), - pressed_(0) { - } - virtual ~MouseView() {} - - virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE { - pressed_++; - return true; - } - - virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE { - entered_++; - } - - virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE { - exited_++; - } - - // Return the number of OnMouseEntered calls and reset the counter. - int EnteredCalls() { - int i = entered_; - entered_ = 0; - return i; - } - - // Return the number of OnMouseExited calls and reset the counter. - int ExitedCalls() { - int i = exited_; - exited_ = 0; - return i; - } - - int pressed() const { return pressed_; } - - private: - int entered_; - int exited_; - - int pressed_; - - DISALLOW_COPY_AND_ASSIGN(MouseView); -}; - // A view that keeps track of the events it receives, but consumes no events. class EventCountView : public View { public: @@ -200,24 +108,6 @@ class ScrollableEventCountView : public EventCountView { DISALLOW_COPY_AND_ASSIGN(ScrollableEventCountView); }; -// A view that does a capture on gesture-begin events. -class GestureCaptureView : public View { - public: - GestureCaptureView() {} - virtual ~GestureCaptureView() {} - - private: - // Overridden from View: - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { - if (event->type() == ui::ET_GESTURE_BEGIN) { - GetWidget()->SetCapture(this); - event->StopPropagation(); - } - } - - DISALLOW_COPY_AND_ASSIGN(GestureCaptureView); -}; - // A view that implements GetMinimumSize. class MinimumSizeFrameView : public NativeFrameView { public: @@ -265,147 +155,6 @@ class EventCountHandler : public ui::EventHandler { DISALLOW_COPY_AND_ASSIGN(EventCountHandler); }; -// A View that shows a different widget, sets capture on that widget, and -// initiates a nested message-loop when it receives a mouse-press event. -class NestedLoopCaptureView : public View { - public: - explicit NestedLoopCaptureView(Widget* widget) : widget_(widget) {} - virtual ~NestedLoopCaptureView() {} - - private: - // Overridden from View: - virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE { - // Start a nested loop. - widget_->Show(); - widget_->SetCapture(widget_->GetContentsView()); - EXPECT_TRUE(widget_->HasCapture()); - - base::MessageLoopForUI* loop = base::MessageLoopForUI::current(); - base::MessageLoop::ScopedNestableTaskAllower allow(loop); - - base::RunLoop run_loop; -#if defined(USE_AURA) - run_loop.set_dispatcher(aura::Env::GetInstance()->GetDispatcher()); -#endif - run_loop.Run(); - return true; - } - - Widget* widget_; - - DISALLOW_COPY_AND_ASSIGN(NestedLoopCaptureView); -}; - -// A View that closes the Widget and exits the current message-loop when it -// receives a mouse-release event. -class ExitLoopOnRelease : public View { - public: - ExitLoopOnRelease() {} - virtual ~ExitLoopOnRelease() {} - - private: - // Overridden from View: - virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE { - GetWidget()->Close(); - base::MessageLoop::current()->QuitNow(); - } - - DISALLOW_COPY_AND_ASSIGN(ExitLoopOnRelease); -}; - -class WidgetTest : public ViewsTestBase { - public: - WidgetTest() {} - virtual ~WidgetTest() {} - - NativeWidget* CreatePlatformNativeWidget( - internal::NativeWidgetDelegate* delegate) { - return new NativeWidgetPlatformForTest(delegate); - } - - Widget* CreateTopLevelPlatformWidget() { - Widget* toplevel = new Widget; - Widget::InitParams toplevel_params = - CreateParams(Widget::InitParams::TYPE_WINDOW); - toplevel_params.native_widget = CreatePlatformNativeWidget(toplevel); - toplevel->Init(toplevel_params); - return toplevel; - } - - Widget* CreateTopLevelFramelessPlatformWidget() { - Widget* toplevel = new Widget; - Widget::InitParams toplevel_params = - CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); - toplevel_params.native_widget = CreatePlatformNativeWidget(toplevel); - toplevel->Init(toplevel_params); - return toplevel; - } - - Widget* CreateChildPlatformWidget(gfx::NativeView parent_native_view) { - Widget* child = new Widget; - Widget::InitParams child_params = - CreateParams(Widget::InitParams::TYPE_CONTROL); - child_params.native_widget = CreatePlatformNativeWidget(child); - child_params.parent = parent_native_view; - child->Init(child_params); - child->SetContentsView(new View); - return child; - } - -#if defined(OS_WIN) && !defined(USE_AURA) - // On Windows, it is possible for us to have a child window that is - // TYPE_POPUP. - Widget* CreateChildPopupPlatformWidget(gfx::NativeView parent_native_view) { - Widget* child = new Widget; - Widget::InitParams child_params = - CreateParams(Widget::InitParams::TYPE_POPUP); - child_params.child = true; - child_params.native_widget = CreatePlatformNativeWidget(child); - child_params.parent = parent_native_view; - child->Init(child_params); - child->SetContentsView(new View); - return child; - } -#endif - - Widget* CreateTopLevelNativeWidget() { - Widget* toplevel = new Widget; - Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); - toplevel->Init(params); - return toplevel; - } - - Widget* CreateChildNativeWidgetWithParent(Widget* parent) { - Widget* child = new Widget; - Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_CONTROL); - params.parent = parent->GetNativeView(); - child->Init(params); - child->SetContentsView(new View); - return child; - } - - Widget* CreateChildNativeWidget() { - return CreateChildNativeWidgetWithParent(NULL); - } - - View* GetMousePressedHandler(internal::RootView* root_view) { - return root_view->mouse_pressed_handler_; - } - - View* GetMouseMoveHandler(internal::RootView* root_view) { - return root_view->mouse_move_handler_; - } - - View* GetGestureHandler(internal::RootView* root_view) { - return root_view->gesture_handler_; - } -}; - -bool WidgetHasMouseCapture(const Widget* widget) { - return static_cast<const internal::NativeWidgetPrivate*>(widget-> - native_widget())->HasCapture(); -} - ui::WindowShowState GetWidgetShowState(const Widget* widget) { // Use IsMaximized/IsMinimized/IsFullScreen instead of GetWindowPlacement // because the former is implemented on all platforms but the latter is not. @@ -452,112 +201,6 @@ TEST_F(WidgetTest, GetTopLevelWidget_Native) { // |child| should be automatically destroyed with |toplevel|. } -// Tests some grab/ungrab events. -TEST_F(WidgetTest, DISABLED_GrabUngrab) { - Widget* toplevel = CreateTopLevelPlatformWidget(); - Widget* child1 = CreateChildNativeWidgetWithParent(toplevel); - Widget* child2 = CreateChildNativeWidgetWithParent(toplevel); - - toplevel->SetBounds(gfx::Rect(0, 0, 500, 500)); - - child1->SetBounds(gfx::Rect(10, 10, 300, 300)); - View* view = new MouseView(); - view->SetBounds(0, 0, 300, 300); - child1->GetRootView()->AddChildView(view); - - child2->SetBounds(gfx::Rect(200, 10, 200, 200)); - view = new MouseView(); - view->SetBounds(0, 0, 200, 200); - child2->GetRootView()->AddChildView(view); - - toplevel->Show(); - RunPendingMessages(); - - // Click on child1 - gfx::Point p1(45, 45); - ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, p1, p1, - ui::EF_LEFT_MOUSE_BUTTON); - toplevel->OnMouseEvent(&pressed); - - EXPECT_TRUE(WidgetHasMouseCapture(toplevel)); - EXPECT_TRUE(WidgetHasMouseCapture(child1)); - EXPECT_FALSE(WidgetHasMouseCapture(child2)); - - ui::MouseEvent released(ui::ET_MOUSE_RELEASED, p1, p1, - ui::EF_LEFT_MOUSE_BUTTON); - toplevel->OnMouseEvent(&released); - - EXPECT_FALSE(WidgetHasMouseCapture(toplevel)); - EXPECT_FALSE(WidgetHasMouseCapture(child1)); - EXPECT_FALSE(WidgetHasMouseCapture(child2)); - - RunPendingMessages(); - - // Click on child2 - gfx::Point p2(315, 45); - ui::MouseEvent pressed2(ui::ET_MOUSE_PRESSED, p2, p2, - ui::EF_LEFT_MOUSE_BUTTON); - toplevel->OnMouseEvent(&pressed2); - EXPECT_TRUE(pressed2.handled()); - EXPECT_TRUE(WidgetHasMouseCapture(toplevel)); - EXPECT_TRUE(WidgetHasMouseCapture(child2)); - EXPECT_FALSE(WidgetHasMouseCapture(child1)); - - ui::MouseEvent released2(ui::ET_MOUSE_RELEASED, p2, p2, - ui::EF_LEFT_MOUSE_BUTTON); - toplevel->OnMouseEvent(&released2); - EXPECT_FALSE(WidgetHasMouseCapture(toplevel)); - EXPECT_FALSE(WidgetHasMouseCapture(child1)); - EXPECT_FALSE(WidgetHasMouseCapture(child2)); - - toplevel->CloseNow(); -} - -// Tests mouse move outside of the window into the "resize controller" and back -// will still generate an OnMouseEntered and OnMouseExited event.. -TEST_F(WidgetTest, CheckResizeControllerEvents) { - Widget* toplevel = CreateTopLevelPlatformWidget(); - - toplevel->SetBounds(gfx::Rect(0, 0, 100, 100)); - - MouseView* view = new MouseView(); - view->SetBounds(90, 90, 10, 10); - toplevel->GetRootView()->AddChildView(view); - - toplevel->Show(); - RunPendingMessages(); - - // Move to an outside position. - gfx::Point p1(200, 200); - ui::MouseEvent moved_out(ui::ET_MOUSE_MOVED, p1, p1, ui::EF_NONE); - toplevel->OnMouseEvent(&moved_out); - EXPECT_EQ(0, view->EnteredCalls()); - EXPECT_EQ(0, view->ExitedCalls()); - - // Move onto the active view. - gfx::Point p2(95, 95); - ui::MouseEvent moved_over(ui::ET_MOUSE_MOVED, p2, p2, ui::EF_NONE); - toplevel->OnMouseEvent(&moved_over); - EXPECT_EQ(1, view->EnteredCalls()); - EXPECT_EQ(0, view->ExitedCalls()); - - // Move onto the outer resizing border. - gfx::Point p3(102, 95); - ui::MouseEvent moved_resizer(ui::ET_MOUSE_MOVED, p3, p3, ui::EF_NONE); - toplevel->OnMouseEvent(&moved_resizer); - EXPECT_EQ(0, view->EnteredCalls()); - EXPECT_EQ(1, view->ExitedCalls()); - - // Move onto the view again. - toplevel->OnMouseEvent(&moved_over); - EXPECT_EQ(1, view->EnteredCalls()); - EXPECT_EQ(0, view->ExitedCalls()); - - RunPendingMessages(); - - toplevel->CloseNow(); -} - // Test if a focus manager and an inputmethod work without CHECK failure // when window activation changes. TEST_F(WidgetTest, ChangeActivation) { @@ -941,6 +584,99 @@ TEST_F(WidgetOwnershipTest, } //////////////////////////////////////////////////////////////////////////////// +// Test to verify using various Widget methods doesn't crash when the underlying +// NativeView is destroyed. +// +class WidgetWithDestroyedNativeViewTest : public ViewsTestBase { + public: + WidgetWithDestroyedNativeViewTest() {} + virtual ~WidgetWithDestroyedNativeViewTest() {} + + void InvokeWidgetMethods(Widget* widget) { + widget->GetNativeView(); + widget->GetNativeWindow(); + ui::Accelerator accelerator; + widget->GetAccelerator(0, &accelerator); + widget->GetTopLevelWidget(); + widget->GetWindowBoundsInScreen(); + widget->GetClientAreaBoundsInScreen(); + widget->SetBounds(gfx::Rect(0, 0, 100, 80)); + widget->SetSize(gfx::Size(10, 11)); + widget->SetBoundsConstrained(gfx::Rect(0, 0, 120, 140)); + widget->SetVisibilityChangedAnimationsEnabled(false); + widget->StackAtTop(); + widget->IsClosed(); + widget->Close(); + widget->Show(); + widget->Hide(); + widget->Activate(); + widget->Deactivate(); + widget->IsActive(); + widget->DisableInactiveRendering(); + widget->SetAlwaysOnTop(true); + widget->Maximize(); + widget->Minimize(); + widget->Restore(); + widget->IsMaximized(); + widget->IsFullscreen(); + widget->SetOpacity(0); + widget->SetUseDragFrame(true); + widget->FlashFrame(true); + widget->IsVisible(); + widget->GetThemeProvider(); + widget->GetNativeTheme(); + widget->GetFocusManager(); + widget->GetInputMethod(); + widget->SchedulePaintInRect(gfx::Rect(0, 0, 1, 2)); + widget->IsMouseEventsEnabled(); + widget->SetNativeWindowProperty("xx", widget); + widget->GetNativeWindowProperty("xx"); + widget->GetFocusTraversable(); + widget->GetLayer(); + widget->ReorderNativeViews(); + widget->SetCapture(widget->GetRootView()); + widget->ReleaseCapture(); + widget->HasCapture(); + widget->TooltipTextChanged(widget->GetRootView()); + widget->GetWorkAreaBoundsInScreen(); + // These three crash with NativeWidgetWin, so I'm assuming we don't need + // them to work for the other NativeWidget impls. + // widget->CenterWindow(gfx::Size(50, 60)); + // widget->GetRestoredBounds(); + // widget->ShowInactive(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(WidgetWithDestroyedNativeViewTest); +}; + +TEST_F(WidgetWithDestroyedNativeViewTest, Test) { + { + Widget widget; + Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); + params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + widget.Init(params); + widget.Show(); + + widget.native_widget_private()->CloseNow(); + InvokeWidgetMethods(&widget); + } +#if defined(USE_AURA) && !defined(OS_CHROMEOS) + { + Widget widget; + Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); + params.native_widget = new DesktopNativeWidgetAura(&widget); + params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + widget.Init(params); + widget.Show(); + + widget.native_widget_private()->CloseNow(); + InvokeWidgetMethods(&widget); + } +#endif +} + +//////////////////////////////////////////////////////////////////////////////// // Widget observer tests. // @@ -1178,94 +914,6 @@ TEST_F(WidgetTest, ExitFullscreenRestoreState) { RunPendingMessages(); } -// Checks that if a mouse-press triggers a capture on a different widget (which -// consumes the mouse-release event), then the target of the press does not have -// capture. -TEST_F(WidgetTest, CaptureWidgetFromMousePress) { - // The test creates two widgets: |first| and |second|. - // The View in |first| makes |second| visible, sets capture on it, and starts - // a nested loop (like a menu does). The View in |second| terminates the - // nested loop and closes the widget. - // The test sends a mouse-press event to |first|, and posts a task to send a - // release event to |second|, to make sure that the release event is - // dispatched after the nested loop starts. - - Widget* first = CreateTopLevelFramelessPlatformWidget(); - Widget* second = CreateTopLevelFramelessPlatformWidget(); - - View* container = new NestedLoopCaptureView(second); - first->SetContentsView(container); - - second->SetContentsView(new ExitLoopOnRelease()); - - first->SetSize(gfx::Size(100, 100)); - first->Show(); - - gfx::Point location(20, 20); - base::MessageLoop::current()->PostTask(FROM_HERE, - base::Bind(&Widget::OnMouseEvent, - base::Unretained(second), - base::Owned(new ui::MouseEvent(ui::ET_MOUSE_RELEASED, - location, - location, - ui::EF_LEFT_MOUSE_BUTTON)))); - ui::MouseEvent press(ui::ET_MOUSE_PRESSED, location, location, - ui::EF_LEFT_MOUSE_BUTTON); - first->OnMouseEvent(&press); - EXPECT_FALSE(first->HasCapture()); - first->Close(); - RunPendingMessages(); -} - -TEST_F(WidgetTest, ResetCaptureOnGestureEnd) { - Widget* toplevel = CreateTopLevelFramelessPlatformWidget(); - View* container = new View; - toplevel->SetContentsView(container); - - View* gesture = new GestureCaptureView; - gesture->SetBounds(0, 0, 30, 30); - container->AddChildView(gesture); - - MouseView* mouse = new MouseView; - mouse->SetBounds(30, 0, 30, 30); - container->AddChildView(mouse); - - toplevel->SetSize(gfx::Size(100, 100)); - toplevel->Show(); - - // Start a gesture on |gesture|. - ui::GestureEvent begin(ui::ET_GESTURE_BEGIN, - 15, 15, 0, base::TimeDelta(), - ui::GestureEventDetails(ui::ET_GESTURE_BEGIN, 0, 0), 1); - ui::GestureEvent end(ui::ET_GESTURE_END, - 15, 15, 0, base::TimeDelta(), - ui::GestureEventDetails(ui::ET_GESTURE_END, 0, 0), 1); - toplevel->OnGestureEvent(&begin); - - // Now try to click on |mouse|. Since |gesture| will have capture, |mouse| - // will not receive the event. - gfx::Point click_location(45, 15); - - ui::MouseEvent press(ui::ET_MOUSE_PRESSED, click_location, click_location, - ui::EF_LEFT_MOUSE_BUTTON); - ui::MouseEvent release(ui::ET_MOUSE_RELEASED, click_location, click_location, - ui::EF_LEFT_MOUSE_BUTTON); - - toplevel->OnMouseEvent(&press); - toplevel->OnMouseEvent(&release); - EXPECT_EQ(0, mouse->pressed()); - - // The end of the gesture should release the capture, and pressing on |mouse| - // should now reach |mouse|. - toplevel->OnGestureEvent(&end); - toplevel->OnMouseEvent(&press); - toplevel->OnMouseEvent(&release); - EXPECT_EQ(1, mouse->pressed()); - - toplevel->Close(); - RunPendingMessages(); -} - #if defined(USE_AURA) // The key-event propagation from Widget happens differently on aura and // non-aura systems because of the difference in IME. So this test works only on @@ -1437,27 +1085,28 @@ TEST_F(WidgetTest, DesktopNativeWidgetAuraNoPaintAfterHideTest) { widget.Close(); } -// This class provides functionality to test whether the destruction of full -// screen child windows occurs correctly in desktop AURA without crashing. +// This class provides functionality to create fullscreen and top level popup +// windows. It additionally tests whether the destruction of these windows +// occurs correctly in desktop AURA without crashing. // It provides facilities to test the following cases:- // 1. Child window destroyed which should lead to the destruction of the // parent. // 2. Parent window destroyed which should lead to the child being destroyed. -class DesktopAuraFullscreenChildWindowDestructionTest +class DesktopAuraTopLevelWindowTest : public views::TestViewsDelegate, public aura::WindowObserver { public: - DesktopAuraFullscreenChildWindowDestructionTest() - : full_screen_widget_(NULL), - child_window_(NULL), - parent_destroyed_(false), - child_destroyed_(false) {} + DesktopAuraTopLevelWindowTest() + : top_level_widget_(NULL), + owned_window_(NULL), + owner_destroyed_(false), + owned_window_destroyed_(false) {} - virtual ~DesktopAuraFullscreenChildWindowDestructionTest() { - EXPECT_TRUE(parent_destroyed_); - EXPECT_TRUE(child_destroyed_); - full_screen_widget_ = NULL; - child_window_ = NULL; + virtual ~DesktopAuraTopLevelWindowTest() { + EXPECT_TRUE(owner_destroyed_); + EXPECT_TRUE(owned_window_destroyed_); + top_level_widget_ = NULL; + owned_window_ = NULL; } // views::TestViewsDelegate overrides. @@ -1468,50 +1117,55 @@ class DesktopAuraFullscreenChildWindowDestructionTest params->native_widget = new views::DesktopNativeWidgetAura(delegate); } - void CreateFullscreenChildWindow(const gfx::Rect& bounds) { + void CreateTopLevelWindow(const gfx::Rect& bounds, bool fullscreen) { Widget::InitParams init_params; init_params.type = Widget::InitParams::TYPE_WINDOW; init_params.bounds = bounds; init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; init_params.layer_type = ui::LAYER_NOT_DRAWN; + init_params.accept_events = fullscreen; widget_.Init(init_params); - child_window_ = new aura::Window(&child_window_delegate_); - child_window_->SetType(aura::client::WINDOW_TYPE_NORMAL); - child_window_->Init(ui::LAYER_TEXTURED); - child_window_->SetName("TestFullscreenChildWindow"); - child_window_->SetProperty(aura::client::kShowStateKey, - ui::SHOW_STATE_FULLSCREEN); - child_window_->SetDefaultParentByRootWindow( + owned_window_ = new aura::Window(&child_window_delegate_); + owned_window_->SetType(aura::client::WINDOW_TYPE_NORMAL); + owned_window_->SetName("TestTopLevelWindow"); + if (fullscreen) { + owned_window_->SetProperty(aura::client::kShowStateKey, + ui::SHOW_STATE_FULLSCREEN); + } else { + owned_window_->SetType(aura::client::WINDOW_TYPE_MENU); + } + owned_window_->Init(ui::LAYER_TEXTURED); + owned_window_->SetDefaultParentByRootWindow( widget_.GetNativeView()->GetRootWindow(), gfx::Rect(0, 0, 1900, 1600)); - child_window_->Show(); - child_window_->AddObserver(this); + owned_window_->Show(); + owned_window_->AddObserver(this); - ASSERT_TRUE(child_window_->parent() != NULL); - child_window_->parent()->AddObserver(this); + ASSERT_TRUE(owned_window_->parent() != NULL); + owned_window_->parent()->AddObserver(this); - full_screen_widget_ = - views::Widget::GetWidgetForNativeView(child_window_->parent()); - ASSERT_TRUE(full_screen_widget_ != NULL); + top_level_widget_ = + views::Widget::GetWidgetForNativeView(owned_window_->parent()); + ASSERT_TRUE(top_level_widget_ != NULL); } - void DestroyChildWindow() { - ASSERT_TRUE(child_window_ != NULL); - delete child_window_; + void DestroyOwnedWindow() { + ASSERT_TRUE(owned_window_ != NULL); + delete owned_window_; } - void DestroyParentWindow() { - ASSERT_TRUE(full_screen_widget_ != NULL); - full_screen_widget_->CloseNow(); + void DestroyOwnerWindow() { + ASSERT_TRUE(top_level_widget_ != NULL); + top_level_widget_->CloseNow(); } virtual void OnWindowDestroying(aura::Window* window) OVERRIDE { window->RemoveObserver(this); - if (window == child_window_) { - child_destroyed_ = true; - } else if (window == full_screen_widget_->GetNativeView()) { - parent_destroyed_ = true; + if (window == owned_window_) { + owned_window_destroyed_ = true; + } else if (window == top_level_widget_->GetNativeView()) { + owner_destroyed_ = true; } else { ADD_FAILURE() << "Unexpected window destroyed callback: " << window; } @@ -1519,38 +1173,52 @@ class DesktopAuraFullscreenChildWindowDestructionTest private: views::Widget widget_; - views::Widget* full_screen_widget_; - aura::Window* child_window_; - bool parent_destroyed_; - bool child_destroyed_; + views::Widget* top_level_widget_; + aura::Window* owned_window_; + bool owner_destroyed_; + bool owned_window_destroyed_; aura::test::TestWindowDelegate child_window_delegate_; - DISALLOW_COPY_AND_ASSIGN(DesktopAuraFullscreenChildWindowDestructionTest); + DISALLOW_COPY_AND_ASSIGN(DesktopAuraTopLevelWindowTest); }; -TEST_F(WidgetTest, DesktopAuraFullscreenChildDestroyedBeforeParentTest) { +TEST_F(WidgetTest, DesktopAuraFullscreenWindowDestroyedBeforeOwnerTest) { ViewsDelegate::views_delegate = NULL; - DesktopAuraFullscreenChildWindowDestructionTest full_screen_child_test; - ASSERT_NO_FATAL_FAILURE(full_screen_child_test.CreateFullscreenChildWindow( - gfx::Rect(0, 0, 200, 200))); + DesktopAuraTopLevelWindowTest fullscreen_window; + ASSERT_NO_FATAL_FAILURE(fullscreen_window.CreateTopLevelWindow( + gfx::Rect(0, 0, 200, 200), true)); RunPendingMessages(); - ASSERT_NO_FATAL_FAILURE(full_screen_child_test.DestroyChildWindow()); + ASSERT_NO_FATAL_FAILURE(fullscreen_window.DestroyOwnedWindow()); RunPendingMessages(); } -TEST_F(WidgetTest, DesktopAuraFullscreenChildParentDestroyed) { +TEST_F(WidgetTest, DesktopAuraFullscreenWindowOwnerDestroyed) { ViewsDelegate::views_delegate = NULL; - DesktopAuraFullscreenChildWindowDestructionTest full_screen_child_test; - ASSERT_NO_FATAL_FAILURE(full_screen_child_test.CreateFullscreenChildWindow( - gfx::Rect(0, 0, 200, 200))); + DesktopAuraTopLevelWindowTest fullscreen_window; + ASSERT_NO_FATAL_FAILURE(fullscreen_window.CreateTopLevelWindow( + gfx::Rect(0, 0, 200, 200), true)); RunPendingMessages(); - ASSERT_NO_FATAL_FAILURE(full_screen_child_test.DestroyParentWindow()); + ASSERT_NO_FATAL_FAILURE(fullscreen_window.DestroyOwnerWindow()); RunPendingMessages(); } +// TODO(erg): Disabled on desktop linux until http://crbug.com/288988 is fixed. +#if !defined(OS_LINUX) +TEST_F(WidgetTest, DesktopAuraTopLevelOwnedPopupTest) { + ViewsDelegate::views_delegate = NULL; + DesktopAuraTopLevelWindowTest popup_window; + ASSERT_NO_FATAL_FAILURE(popup_window.CreateTopLevelWindow( + gfx::Rect(0, 0, 200, 200), false)); + + RunPendingMessages(); + ASSERT_NO_FATAL_FAILURE(popup_window.DestroyOwnedWindow()); + RunPendingMessages(); +} +#endif + // Test to ensure that the aura Window's visiblity state is set to visible if // the underlying widget is hidden and then shown. TEST_F(WidgetTest, TestWindowVisibilityAfterHide) { @@ -1574,6 +1242,116 @@ TEST_F(WidgetTest, TestWindowVisibilityAfterHide) { EXPECT_TRUE(widget.GetNativeView()->IsVisible()); } +// The following code verifies we can correctly destroy a Widget from a mouse +// enter/exit. We could test move/drag/enter/exit but in general we don't run +// nested message loops from such events, nor has the code ever really dealt +// with this situation. + +// Class that closes the widget (which ends up deleting it immediately) when the +// appropriate event is received. +class CloseWidgetView : public View { + public: + explicit CloseWidgetView(ui::EventType event_type) + : event_type_(event_type) { + } + + // View overrides: + virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE { + if (!CloseWidget(event)) + View::OnMousePressed(event); + return true; + } + virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE { + if (!CloseWidget(event)) + View::OnMouseDragged(event); + return true; + } + virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE { + if (!CloseWidget(event)) + View::OnMouseReleased(event); + } + virtual void OnMouseMoved(const ui::MouseEvent& event) OVERRIDE { + if (!CloseWidget(event)) + View::OnMouseMoved(event); + } + virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE { + if (!CloseWidget(event)) + View::OnMouseEntered(event); + } + + private: + bool CloseWidget(const ui::LocatedEvent& event) { + if (event.type() == event_type_) { + // Go through NativeWidgetPrivate to simulate what happens if the OS + // deletes the NativeWindow out from under us. + GetWidget()->native_widget_private()->CloseNow(); + return true; + } + return false; + } + + const ui::EventType event_type_; + + DISALLOW_COPY_AND_ASSIGN(CloseWidgetView); +}; + +// Generates two moves (first generates enter, second real move), a press, drag +// and release stopping at |last_event_type|. +void GenerateMouseEvents(Widget* widget, ui::EventType last_event_type) { + const gfx::Rect screen_bounds(widget->GetWindowBoundsInScreen()); + ui::MouseEvent move_event(ui::ET_MOUSE_MOVED, screen_bounds.CenterPoint(), + screen_bounds.CenterPoint(), 0); + aura::RootWindowHostDelegate* rwhd = + widget->GetNativeWindow()->GetRootWindow()->AsRootWindowHostDelegate(); + rwhd->OnHostMouseEvent(&move_event); + if (last_event_type == ui::ET_MOUSE_ENTERED) + return; + rwhd->OnHostMouseEvent(&move_event); + if (last_event_type == ui::ET_MOUSE_MOVED) + return; + + ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, screen_bounds.CenterPoint(), + screen_bounds.CenterPoint(), 0); + rwhd->OnHostMouseEvent(&press_event); + if (last_event_type == ui::ET_MOUSE_PRESSED) + return; + + gfx::Point end_point(screen_bounds.CenterPoint()); + end_point.Offset(1, 1); + ui::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, end_point, end_point, 0); + rwhd->OnHostMouseEvent(&drag_event); + if (last_event_type == ui::ET_MOUSE_DRAGGED) + return; + + ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, end_point, end_point, 0); + rwhd->OnHostMouseEvent(&release_event); +} + +// Creates a widget and invokes GenerateMouseEvents() with |last_event_type|. +void RunCloseWidgetDuringDispatchTest(WidgetTest* test, + ui::EventType last_event_type) { + // |widget| is deleted by CloseWidgetView. + Widget* widget = new Widget; + Widget::InitParams params = + test->CreateParams(Widget::InitParams::TYPE_POPUP); + params.native_widget = new DesktopNativeWidgetAura(widget); + params.bounds = gfx::Rect(0, 0, 50, 100); + widget->Init(params); + widget->SetContentsView(new CloseWidgetView(last_event_type)); + widget->Show(); + GenerateMouseEvents(widget, last_event_type); +} + +// Verifies deleting the widget from a mouse pressed event doesn't crash. +TEST_F(WidgetTest, CloseWidgetDuringMousePress) { + RunCloseWidgetDuringDispatchTest(this, ui::ET_MOUSE_PRESSED); +} + +// Verifies deleting the widget from a mouse released event doesn't crash. +TEST_F(WidgetTest, CloseWidgetDuringMouseReleased) { + RunCloseWidgetDuringDispatchTest(this, ui::ET_MOUSE_RELEASED); +} + #endif // !defined(OS_CHROMEOS) // Tests that wheel events generated from scroll events are targetted to the @@ -1773,64 +1551,6 @@ TEST_F(WidgetTest, SynthesizeMouseMoveEvent) { EXPECT_EQ(1, v2->GetEventCount(ui::ET_MOUSE_ENTERED)); } -TEST_F(WidgetTest, MouseEventsHandled) { - Widget* widget = CreateTopLevelNativeWidget(); - View* root_view = widget->GetRootView(); - -#if defined(USE_AURA) - aura::test::TestCursorClient cursor_client( - widget->GetNativeView()->GetRootWindow()); -#endif - - EventCountView* v1 = new EventCountView(); - v1->SetBounds(0, 0, 10, 10); - root_view->AddChildView(v1); - EventCountView* v2 = new EventCountView(); - v2->SetBounds(0, 10, 10, 10); - root_view->AddChildView(v2); - - gfx::Point cursor_location1(5, 5); - ui::MouseEvent move1(ui::ET_MOUSE_MOVED, cursor_location1, cursor_location1, - ui::EF_NONE); - widget->OnMouseEvent(&move1); - EXPECT_EQ(1, v1->GetEventCount(ui::ET_MOUSE_ENTERED)); - EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_ENTERED)); - EXPECT_EQ(0, v1->GetEventCount(ui::ET_MOUSE_EXITED)); - EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_EXITED)); - v1->ResetCounts(); - v2->ResetCounts(); - - gfx::Point cursor_location2(5, 15); - ui::MouseEvent move2(ui::ET_MOUSE_MOVED, cursor_location2, cursor_location2, - ui::EF_NONE); - widget->OnMouseEvent(&move2); - EXPECT_EQ(0, v1->GetEventCount(ui::ET_MOUSE_ENTERED)); - EXPECT_EQ(1, v2->GetEventCount(ui::ET_MOUSE_ENTERED)); - EXPECT_EQ(1, v1->GetEventCount(ui::ET_MOUSE_EXITED)); - EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_EXITED)); - v1->ResetCounts(); - v2->ResetCounts(); - -#if defined(USE_AURA) - // In Aura, we suppress mouse events if mouse events are disabled. - cursor_client.DisableMouseEvents(); - - widget->OnMouseEvent(&move1); - EXPECT_EQ(0, v1->GetEventCount(ui::ET_MOUSE_ENTERED)); - EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_ENTERED)); - EXPECT_EQ(0, v1->GetEventCount(ui::ET_MOUSE_EXITED)); - EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_EXITED)); - v1->ResetCounts(); - v2->ResetCounts(); - - widget->OnMouseEvent(&move2); - EXPECT_EQ(0, v1->GetEventCount(ui::ET_MOUSE_ENTERED)); - EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_ENTERED)); - EXPECT_EQ(0, v1->GetEventCount(ui::ET_MOUSE_EXITED)); - EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_EXITED)); -#endif -} - // Used by SingleWindowClosing to count number of times WindowClosing() has // been invoked. class ClosingDelegate : public WidgetDelegate { @@ -2063,7 +1783,15 @@ class RootViewTestView : public View { }; // Checks if RootView::*_handler_ fields are unset when widget is hidden. -TEST_F(WidgetTest, TestRootViewHandlersWhenHidden) { +// Fails on chromium.webkit Windows bot, see crbug.com/264872. +#if defined(OS_WIN) +#define MAYBE_DisableTestRootViewHandlersWhenHidden\ + DISABLED_TestRootViewHandlersWhenHidden +#else +#define MAYBE_DisableTestRootViewHandlersWhenHidden\ + TestRootViewHandlersWhenHidden +#endif +TEST_F(WidgetTest, MAYBE_DisableTestRootViewHandlersWhenHidden) { Widget* widget = CreateTopLevelNativeWidget(); widget->SetBounds(gfx::Rect(0, 0, 300, 300)); View* view = new RootViewTestView(); @@ -2112,5 +1840,37 @@ TEST_F(WidgetTest, TestRootViewHandlersWhenHidden) { widget->Close(); } +// Test the result of Widget::GetAllChildWidgets(). +TEST_F(WidgetTest, GetAllChildWidgets) { + // Create the following widget hierarchy: + // + // toplevel + // +-- w1 + // +-- w11 + // +-- w2 + // +-- w21 + // +-- w22 + Widget* toplevel = CreateTopLevelPlatformWidget(); + Widget* w1 = CreateChildPlatformWidget(toplevel->GetNativeView()); + Widget* w11 = CreateChildPlatformWidget(w1->GetNativeView()); + Widget* w2 = CreateChildPlatformWidget(toplevel->GetNativeView()); + Widget* w21 = CreateChildPlatformWidget(w2->GetNativeView()); + Widget* w22 = CreateChildPlatformWidget(w2->GetNativeView()); + + std::set<Widget*> expected; + expected.insert(toplevel); + expected.insert(w1); + expected.insert(w11); + expected.insert(w2); + expected.insert(w21); + expected.insert(w22); + + std::set<Widget*> widgets; + Widget::GetAllChildWidgets(toplevel->GetNativeView(), &widgets); + + EXPECT_EQ(expected.size(), widgets.size()); + EXPECT_TRUE(std::equal(expected.begin(), expected.end(), widgets.begin())); +} + } // namespace test } // namespace views diff --git a/chromium/ui/views/win/fullscreen_handler.cc b/chromium/ui/views/win/fullscreen_handler.cc index 33a0475095a..2fe8ceaf2b5 100644 --- a/chromium/ui/views/win/fullscreen_handler.cc +++ b/chromium/ui/views/win/fullscreen_handler.cc @@ -5,6 +5,7 @@ #include "ui/views/win/fullscreen_handler.h" #include "base/logging.h" +#include "base/win/win_util.h" #include "ui/gfx/rect.h" #include "ui/views/win/scoped_fullscreen_visibility.h" @@ -75,8 +76,8 @@ void FullscreenHandler::SetFullscreenImpl(bool fullscreen, bool for_metro) { if (!for_metro) { MONITORINFO monitor_info; monitor_info.cbSize = sizeof(monitor_info); - GetMonitorInfo(MonitorFromWindow(hwnd_, MONITOR_DEFAULTTONEAREST), - &monitor_info); + base::win::GetMonitorInfoWrapper( + MonitorFromWindow(hwnd_, MONITOR_DEFAULTTONEAREST), &monitor_info); gfx::Rect window_rect(monitor_info.rcMonitor); SetWindowPos(hwnd_, NULL, window_rect.x(), window_rect.y(), window_rect.width(), window_rect.height(), diff --git a/chromium/ui/views/win/hwnd_message_handler.cc b/chromium/ui/views/win/hwnd_message_handler.cc index 1a627092732..b29f62da5cb 100644 --- a/chromium/ui/views/win/hwnd_message_handler.cc +++ b/chromium/ui/views/win/hwnd_message_handler.cc @@ -9,17 +9,16 @@ #include "base/bind.h" #include "base/debug/trace_event.h" +#include "base/win/win_util.h" #include "base/win/windows_version.h" -#include "ui/base/events/event.h" -#include "ui/base/events/event_utils.h" #include "ui/base/gestures/gesture_sequence.h" -#include "ui/base/keycodes/keyboard_code_conversion_win.h" #include "ui/base/touch/touch_enabled.h" -#include "ui/base/win/dpi.h" -#include "ui/base/win/hwnd_util.h" #include "ui/base/win/mouse_wheel_util.h" #include "ui/base/win/shell.h" #include "ui/base/win/touch_input.h" +#include "ui/events/event.h" +#include "ui/events/event_utils.h" +#include "ui/events/keycodes/keyboard_code_conversion_win.h" #include "ui/gfx/canvas.h" #include "ui/gfx/canvas_skia_paint.h" #include "ui/gfx/icon_util.h" @@ -27,6 +26,8 @@ #include "ui/gfx/path.h" #include "ui/gfx/path_win.h" #include "ui/gfx/screen.h" +#include "ui/gfx/win/dpi.h" +#include "ui/gfx/win/hwnd_util.h" #include "ui/native_theme/native_theme_win.h" #include "ui/views/views_delegate.h" #include "ui/views/widget/monitor_win.h" @@ -180,7 +181,7 @@ bool GetMonitorAndRects(const RECT& rect, return false; MONITORINFO monitor_info = { 0 }; monitor_info.cbSize = sizeof(monitor_info); - GetMonitorInfo(*monitor, &monitor_info); + base::win::GetMonitorInfoWrapper(*monitor, &monitor_info); *monitor_rect = gfx::Rect(monitor_info.rcMonitor); *work_area = gfx::Rect(monitor_info.rcWork); return true; @@ -374,7 +375,8 @@ class HWNDMessageHandler::ScopedRedrawLock { HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate) : delegate_(delegate), fullscreen_handler_(new FullscreenHandler), - close_widget_factory_(this), + weak_factory_(this), + waiting_for_close_now_(false), remove_standard_frame_(false), use_system_default_icon_(false), restore_focus_when_enabled_(false), @@ -383,22 +385,19 @@ HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate) active_mouse_tracking_flags_(0), is_right_mouse_pressed_on_caption_(false), lock_updates_count_(0), - destroyed_(NULL), ignore_window_pos_changes_(false), - ignore_pos_changes_factory_(this), last_monitor_(NULL), use_layered_buffer_(false), layered_alpha_(255), - paint_layered_window_factory_(this), + waiting_for_redraw_layered_window_contents_(false), can_update_layered_window_(true), is_first_nccalc_(true), - autohide_factory_(this) { + autohide_factory_(this), + id_generator_(0) { } HWNDMessageHandler::~HWNDMessageHandler() { delegate_ = NULL; - if (destroyed_ != NULL) - *destroyed_ = true; // Prevent calls back into this class via WNDPROC now that we've been // destroyed. ClearUserData(); @@ -437,15 +436,15 @@ void HWNDMessageHandler::Close() { // they can activate as foreground windows upon this window's destruction. RestoreEnabledIfNecessary(); - if (!close_widget_factory_.HasWeakPtrs()) { + if (!waiting_for_close_now_) { // And we delay the close so that if we are called from an ATL callback, // we don't destroy the window before the callback returned (as the caller // may delete ourselves on destroy and the ATL callback would still // dereference us when the callback returns). + waiting_for_close_now_ = true; base::MessageLoop::current()->PostTask( FROM_HERE, - base::Bind(&HWNDMessageHandler::CloseNow, - close_widget_factory_.GetWeakPtr())); + base::Bind(&HWNDMessageHandler::CloseNow, weak_factory_.GetWeakPtr())); } } @@ -454,6 +453,7 @@ void HWNDMessageHandler::CloseNow() { // switch which will have reactivated the browser window and closed us, so // we need to check to see if we're still a window before trying to destroy // ourself. + waiting_for_close_now_ = false; if (IsWindow(hwnd())) DestroyWindow(hwnd()); } @@ -503,7 +503,7 @@ void HWNDMessageHandler::GetWindowPlacement( } else { MONITORINFO mi; mi.cbSize = sizeof(mi); - const bool succeeded = GetMonitorInfo( + const bool succeeded = base::win::GetMonitorInfoWrapper( MonitorFromWindow(hwnd(), MONITOR_DEFAULTTONEAREST), &mi) != 0; DCHECK(succeeded); @@ -543,7 +543,7 @@ void HWNDMessageHandler::CenterWindow(const gfx::Size& size) { HWND parent = GetParent(hwnd()); if (!IsWindow(hwnd())) parent = ::GetWindow(hwnd(), GW_OWNER); - ui::CenterAndSizeWindow(parent, hwnd(), size); + gfx::CenterAndSizeWindow(parent, hwnd(), size); } void HWNDMessageHandler::SetRegion(HRGN region) { @@ -687,6 +687,12 @@ bool HWNDMessageHandler::IsMaximized() const { bool HWNDMessageHandler::RunMoveLoop(const gfx::Vector2d& drag_offset) { ReleaseCapture(); MoveLoopMouseWatcher watcher(this); +#if defined(USE_AURA) + // In Aura, we handle touch events asynchronously. So we need to allow nested + // tasks while in windows move loop. + base::MessageLoop::ScopedNestableTaskAllower allow_nested( + base::MessageLoop::current()); +#endif SendMessage(hwnd(), WM_SYSCOMMAND, SC_MOVE | 0x0002, GetMessagePos()); // Windows doesn't appear to offer a way to determine whether the user // canceled the move or not. We assume if the user released the mouse it was @@ -795,11 +801,12 @@ void HWNDMessageHandler::SchedulePaintInRect(const gfx::Rect& rect) { // receive calls to DidProcessMessage(). This only seems to affect layered // windows, so we schedule a redraw manually using a task, since those never // seem to be starved. Also, wtf. - if (!paint_layered_window_factory_.HasWeakPtrs()) { + if (!waiting_for_redraw_layered_window_contents_) { + waiting_for_redraw_layered_window_contents_ = true; base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind(&HWNDMessageHandler::RedrawLayeredWindowContents, - paint_layered_window_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr())); } } else { // InvalidateRect() expects client coordinates. @@ -843,7 +850,7 @@ void HWNDMessageHandler::DispatchKeyEventPostIME(const ui::KeyEvent& key) { } //////////////////////////////////////////////////////////////////////////////// -// HWNDMessageHandler, ui::WindowImpl overrides: +// HWNDMessageHandler, gfx::WindowImpl overrides: HICON HWNDMessageHandler::GetDefaultWindowIcon() const { if (use_system_default_icon_) @@ -870,7 +877,17 @@ LRESULT HWNDMessageHandler::OnWndProc(UINT message, #endif // Otherwise we handle everything else. - if (!ProcessWindowMessage(window, message, w_param, l_param, result)) + // NOTE: We inline ProcessWindowMessage() as 'this' may be destroyed during + // dispatch and ProcessWindowMessage() doesn't deal with that well. + const BOOL old_msg_handled = m_bMsgHandled; + base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr()); + const BOOL processed = + _ProcessWindowMessage(window, message, w_param, l_param, result, 0); + if (!ref) + return 0; + m_bMsgHandled = old_msg_handled; + + if (!processed) result = DefWindowProc(window, message, w_param, l_param); // DefWindowProc() may have destroyed the window in a nested message loop. @@ -880,14 +897,17 @@ LRESULT HWNDMessageHandler::OnWndProc(UINT message, if (delegate_) delegate_->PostHandleMSG(message, w_param, l_param); if (message == WM_NCDESTROY) { +#if !defined(USE_AURA) base::MessageLoopForUI::current()->RemoveObserver(this); +#endif if (delegate_) delegate_->HandleDestroyed(); } // Only top level widget should store/restore focus. if (message == WM_ACTIVATE && delegate_->CanSaveFocus()) - PostProcessActivateMessage(LOWORD(w_param)); + PostProcessActivateMessage(LOWORD(w_param), !!HIWORD(w_param)); + if (message == WM_ENABLE && restore_focus_when_enabled_) { // This path should be executed only for top level as // restore_focus_when_enabled_ is set in PostProcessActivateMessage. @@ -938,9 +958,10 @@ void HWNDMessageHandler::SetInitialFocus() { } } -void HWNDMessageHandler::PostProcessActivateMessage(int activation_state) { +void HWNDMessageHandler::PostProcessActivateMessage(int activation_state, + bool minimized) { DCHECK(delegate_->CanSaveFocus()); - if (WA_INACTIVE == activation_state) { + if (WA_INACTIVE == activation_state || minimized) { // We might get activated/inactivated without being enabled, so we need to // clear restore_focus_when_enabled_. restore_focus_when_enabled_ = false; @@ -1012,11 +1033,17 @@ void HWNDMessageHandler::ClientAreaSizeChanged() { if (!IsMinimized()) { if (delegate_->WidgetSizeIsClientSize()) { GetClientRect(hwnd(), &r); - // This is needed due to a hack that works around a "feature" in - // Windows's handling of WM_NCCALCSIZE. See the comment near the end of - // GetClientAreaInsets for more details. - if (remove_standard_frame_ && !IsMaximized()) - r.bottom += kClientAreaBottomInsetHack; + gfx::Insets insets; + bool got_insets = GetClientAreaInsets(&insets); + if (got_insets) { + // This is needed due to a hack that works around a "feature" in + // Windows's handling of WM_NCCALCSIZE. See the comment near the end of + // GetClientAreaInsets for more details. + if ((remove_standard_frame_ && !IsMaximized()) || + !fullscreen_handler_->fullscreen()) { + r.bottom += kClientAreaBottomInsetHack; + } + } } else { GetWindowRect(hwnd(), &r); } @@ -1073,11 +1100,6 @@ bool HWNDMessageHandler::GetClientAreaInsets(gfx::Insets* insets) const { return true; } -#if defined(USE_AURA) - // The -1 hack below breaks rendering in Aura. - // See http://crbug.com/172099 http://crbug.com/267131 - *insets = gfx::Insets(); -#else // This is weird, but highly essential. If we don't offset the bottom edge // of the client rect, the window client area and window area will match, // and when returning to glass rendering mode from non-glass, the client @@ -1089,8 +1111,11 @@ bool HWNDMessageHandler::GetClientAreaInsets(gfx::Insets* insets) const { // rect when using the opaque frame. // Note: this is only required for non-fullscreen windows. Note that // fullscreen windows are in restored state, not maximized. - *insets = gfx::Insets(0, 0, fullscreen_handler_->fullscreen() ? 0 : 1, 0); -#endif + // Note that previously we used to inset by 1 instead of outset, but that + // doesn't work with Aura: http://crbug.com/172099 http://crbug.com/277228 + *insets = gfx::Insets( + 0, 0, + fullscreen_handler_->fullscreen() ? 0 : kClientAreaBottomInsetHack, 0); return true; } @@ -1120,7 +1145,7 @@ void HWNDMessageHandler::ResetWindowRegion(bool force) { HMONITOR monitor = MonitorFromWindow(hwnd(), MONITOR_DEFAULTTONEAREST); MONITORINFO mi; mi.cbSize = sizeof mi; - GetMonitorInfo(monitor, &mi); + base::win::GetMonitorInfoWrapper(monitor, &mi); CRect work_rect = mi.rcWork; work_rect.OffsetRect(-window_rect.left, -window_rect.top); new_region = CreateRectRgnIndirect(&work_rect); @@ -1146,14 +1171,11 @@ LRESULT HWNDMessageHandler::DefWindowProcWithRedrawLock(UINT message, LPARAM l_param) { ScopedRedrawLock lock(this); // The Widget and HWND can be destroyed in the call to DefWindowProc, so use - // the |destroyed_| flag to avoid unlocking (and crashing) after destruction. - bool destroyed = false; - destroyed_ = &destroyed; + // the WeakPtrFactory to avoid unlocking (and crashing) after destruction. + base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr()); LRESULT result = DefWindowProc(hwnd(), message, w_param, l_param); - if (destroyed) + if (!ref) lock.CancelUnlockOperation(); - else - destroyed_ = NULL; return result; } @@ -1188,6 +1210,10 @@ void HWNDMessageHandler::UnlockUpdates(bool force) { } void HWNDMessageHandler::RedrawInvalidRect() { +// TODO(cpu): Remove the caller and this class as a message loop observer +// because we don't need agressive repaints via RDW_UPDATENOW in Aura. The +// general tracking bug for repaint issues is 177115. +#if !defined(USE_AURA) if (!use_layered_buffer_) { RECT r = { 0, 0, 0, 0 }; if (GetUpdateRect(hwnd(), &r, FALSE) && !IsRectEmpty(&r)) { @@ -1195,15 +1221,17 @@ void HWNDMessageHandler::RedrawInvalidRect() { RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN); } } +#endif } void HWNDMessageHandler::RedrawLayeredWindowContents() { + waiting_for_redraw_layered_window_contents_ = false; if (invalid_rect_.IsEmpty()) return; // We need to clip to the dirty rect ourselves. layered_window_contents_->sk_canvas()->save(SkCanvas::kClip_SaveFlag); - double scale = ui::win::GetDeviceScaleFactor(); + double scale = gfx::win::GetDeviceScaleFactor(); layered_window_contents_->sk_canvas()->scale( SkScalar(scale),SkScalar(scale)); layered_window_contents_->ClipRect(invalid_rect_); @@ -1313,11 +1341,13 @@ LRESULT HWNDMessageHandler::OnCreate(CREATESTRUCT* create_struct) { // creation time. ClientAreaSizeChanged(); +#if !defined(USE_AURA) // We need to add ourselves as a message loop observer so that we can repaint // aggressively if the contents of our window become invalid. Unfortunately // WM_PAINT messages are starved and we get flickery redrawing when resizing // if we do not do this. base::MessageLoopForUI::current()->AddObserver(this); +#endif delegate_->HandleCreate(); @@ -1496,7 +1526,7 @@ LRESULT HWNDMessageHandler::OnMouseRange(UINT message, w_param = SendMessage(hwnd(), WM_NCHITTEST, 0, MAKELPARAM(screen_point.x, screen_point.y)); if (w_param == HTCAPTION || w_param == HTSYSMENU) { - ui::ShowSystemMenuAtPoint(hwnd(), gfx::Point(screen_point)); + gfx::ShowSystemMenuAtPoint(hwnd(), gfx::Point(screen_point)); return 0; } } else if (message == WM_NCLBUTTONDOWN && delegate_->IsUsingCustomFrame()) { @@ -1556,7 +1586,12 @@ LRESULT HWNDMessageHandler::OnMouseRange(UINT message, delegate_->HandleMouseEvent(ui::MouseWheelEvent(msg))) ? 0 : 1; } + // There are cases where the code handling the message destroys the window, + // so use the weak ptr to check if destruction occured or not. + base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr()); bool handled = delegate_->HandleMouseEvent(event); + if (!ref.get()) + return 0; if (!handled && message == WM_NCLBUTTONDOWN && w_param != HTSYSMENU && delegate_->IsUsingCustomFrame()) { // TODO(msw): Eliminate undesired painting, or re-evaluate this workaround. @@ -1567,7 +1602,8 @@ LRESULT HWNDMessageHandler::OnMouseRange(UINT message, handled = true; } - SetMsgHandled(handled); + if (ref.get()) + SetMsgHandled(handled); return 0; } @@ -1591,6 +1627,8 @@ LRESULT HWNDMessageHandler::OnNCActivate(UINT message, // cleared before it is converted to BOOL. BOOL active = static_cast<BOOL>(LOWORD(w_param)); + bool inactive_rendering_disabled = delegate_->IsInactiveRenderingDisabled(); + if (delegate_->CanActivate()) delegate_->HandleActivationChanged(!!active); @@ -1603,7 +1641,6 @@ LRESULT HWNDMessageHandler::OnNCActivate(UINT message, return TRUE; // On activation, lift any prior restriction against rendering as inactive. - bool inactive_rendering_disabled = delegate_->IsInactiveRenderingDisabled(); if (active && inactive_rendering_disabled) delegate_->EnableInactiveRendering(); @@ -2039,11 +2076,17 @@ void HWNDMessageHandler::OnThemeChanged() { LRESULT HWNDMessageHandler::OnTouchEvent(UINT message, WPARAM w_param, LPARAM l_param) { + // Handle touch events only on Aura for now. +#if !defined(USE_AURA) + SetMsgHandled(FALSE); + return 0; +#endif int num_points = LOWORD(w_param); scoped_ptr<TOUCHINPUT[]> input(new TOUCHINPUT[num_points]); if (ui::GetTouchInputInfoWrapper(reinterpret_cast<HTOUCHINPUT>(l_param), num_points, input.get(), sizeof(TOUCHINPUT))) { + TouchEvents touch_events; for (int i = 0; i < num_points; ++i) { ui::EventType touch_event_type = ui::ET_UNKNOWN; @@ -2056,26 +2099,32 @@ LRESULT HWNDMessageHandler::OnTouchEvent(UINT message, } else if (input[i].dwFlags & TOUCHEVENTF_MOVE) { touch_event_type = ui::ET_TOUCH_MOVED; } - // Handle touch events only on Aura for now. -#if defined(USE_AURA) if (touch_event_type != ui::ET_UNKNOWN) { POINT point; point.x = TOUCH_COORD_TO_PIXEL(input[i].x) / - ui::win::GetUndocumentedDPIScale(); + gfx::win::GetUndocumentedDPITouchScale(); point.y = TOUCH_COORD_TO_PIXEL(input[i].y) / - ui::win::GetUndocumentedDPIScale(); + gfx::win::GetUndocumentedDPITouchScale(); ScreenToClient(hwnd(), &point); ui::TouchEvent event( touch_event_type, gfx::Point(point.x, point.y), - input[i].dwID % ui::GestureSequence::kMaxGesturePoints, + id_generator_.GetGeneratedID(input[i].dwID), base::TimeDelta::FromMilliseconds(input[i].dwTime)); - delegate_->HandleTouchEvent(event); + touch_events.push_back(event); + if (touch_event_type == ui::ET_TOUCH_RELEASED) + id_generator_.ReleaseNumber(input[i].dwID); } -#endif } + // Handle the touch events asynchronously. We need this because touch + // events on windows don't fire if we enter a modal loop in the context of + // a touch event. + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&HWNDMessageHandler::HandleTouchEvents, + weak_factory_.GetWeakPtr(), touch_events)); } CloseTouchInputHandle(reinterpret_cast<HTOUCHINPUT>(l_param)); SetMsgHandled(FALSE); @@ -2137,11 +2186,10 @@ void HWNDMessageHandler::OnWindowPosChanging(WINDOWPOS* window_pos) { // likes to (incorrectly) recalculate what our position/size should be // and send us further updates. ignore_window_pos_changes_ = true; - DCHECK(!ignore_pos_changes_factory_.HasWeakPtrs()); base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind(&HWNDMessageHandler::StopIgnoringPosChanges, - ignore_pos_changes_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr())); } last_monitor_ = monitor; last_monitor_rect_ = monitor_rect; @@ -2155,6 +2203,11 @@ void HWNDMessageHandler::OnWindowPosChanging(WINDOWPOS* window_pos) { window_pos->flags &= ~SWP_SHOWWINDOW; } + if (window_pos->flags & SWP_SHOWWINDOW) + delegate_->HandleVisibilityChanging(true); + else if (window_pos->flags & SWP_HIDEWINDOW) + delegate_->HandleVisibilityChanging(false); + SetMsgHandled(FALSE); } @@ -2174,4 +2227,9 @@ void HWNDMessageHandler::OnWindowPosChanged(WINDOWPOS* window_pos) { SetMsgHandled(FALSE); } +void HWNDMessageHandler::HandleTouchEvents(const TouchEvents& touch_events) { + for (size_t i = 0; i < touch_events.size(); ++i) + delegate_->HandleTouchEvent(touch_events[i]); +} + } // namespace views diff --git a/chromium/ui/views/win/hwnd_message_handler.h b/chromium/ui/views/win/hwnd_message_handler.h index c1c724cd1db..1751a829dbb 100644 --- a/chromium/ui/views/win/hwnd_message_handler.h +++ b/chromium/ui/views/win/hwnd_message_handler.h @@ -11,6 +11,7 @@ #include <windows.h> #include <set> +#include <vector> #include "base/basictypes.h" #include "base/compiler_specific.h" @@ -20,9 +21,11 @@ #include "base/strings/string16.h" #include "base/win/win_util.h" #include "ui/base/accessibility/accessibility_types.h" +#include "ui/events/event.h" +#include "ui/base/sequential_id_generator.h" #include "ui/base/ui_base_types.h" -#include "ui/base/win/window_impl.h" #include "ui/gfx/rect.h" +#include "ui/gfx/win/window_impl.h" #include "ui/views/ime/input_method_delegate.h" #include "ui/views/views_export.h" @@ -56,7 +59,7 @@ const int WM_NCUAHDRAWFRAME = 0xAF; // implementation. // TODO(beng): This object should eventually *become* the WindowImpl. class VIEWS_EXPORT HWNDMessageHandler : - public ui::WindowImpl, + public gfx::WindowImpl, public internal::InputMethodDelegate, public base::MessageLoopForUI::Observer { public: @@ -177,7 +180,7 @@ class VIEWS_EXPORT HWNDMessageHandler : // Called after the WM_ACTIVATE message has been processed by the default // windows procedure. - void PostProcessActivateMessage(int activation_state); + void PostProcessActivateMessage(int activation_state, bool minimized); // Enables disabled owner windows that may have been disabled due to this // window's modality. @@ -288,8 +291,8 @@ class VIEWS_EXPORT HWNDMessageHandler : MSG_WM_CREATE(OnCreate) MSG_WM_DESTROY(OnDestroy) MSG_WM_DISPLAYCHANGE(OnDisplayChange) - MSG_WM_ERASEBKGND(OnEraseBkgnd) MSG_WM_ENTERSIZEMOVE(OnEnterSizeMove) + MSG_WM_ERASEBKGND(OnEraseBkgnd) MSG_WM_EXITSIZEMOVE(OnExitSizeMove) MSG_WM_GETMINMAXINFO(OnGetMinMaxInfo) MSG_WM_INITMENU(OnInitMenu) @@ -309,8 +312,8 @@ class VIEWS_EXPORT HWNDMessageHandler : MSG_WM_SIZE(OnSize) MSG_WM_SYSCOMMAND(OnSysCommand) MSG_WM_THEMECHANGED(OnThemeChanged) - MSG_WM_WINDOWPOSCHANGING(OnWindowPosChanging) MSG_WM_WINDOWPOSCHANGED(OnWindowPosChanged) + MSG_WM_WINDOWPOSCHANGING(OnWindowPosChanging) END_MSG_MAP() // Message Handlers. @@ -364,11 +367,20 @@ class VIEWS_EXPORT HWNDMessageHandler : void OnWindowPosChanging(WINDOWPOS* window_pos); void OnWindowPosChanged(WINDOWPOS* window_pos); + typedef std::vector<ui::TouchEvent> TouchEvents; + // Helper to handle the list of touch events passed in. We need this because + // touch events on windows don't fire if we enter a modal loop in the context + // of a touch event. + void HandleTouchEvents(const TouchEvents& touch_events); + HWNDMessageHandlerDelegate* delegate_; scoped_ptr<FullscreenHandler> fullscreen_handler_; - base::WeakPtrFactory<HWNDMessageHandler> close_widget_factory_; + base::WeakPtrFactory<HWNDMessageHandler> weak_factory_; + + // Set to true in Close() and false is CloseNow(). + bool waiting_for_close_now_; bool remove_standard_frame_; @@ -406,11 +418,6 @@ class VIEWS_EXPORT HWNDMessageHandler : // If this is greater than zero, the widget should be locked against updates. int lock_updates_count_; - // This flag can be initialized and checked after certain operations (such as - // DefWindowProc) to avoid stack-controlled functions (such as unlocking the - // Window with a ScopedRedrawLock) after destruction. - bool* destroyed_; - // Window resizing ----------------------------------------------------------- // When true, this flag makes us discard incoming SetWindowPos() requests that @@ -418,10 +425,6 @@ class VIEWS_EXPORT HWNDMessageHandler : // activation, etc.) bool ignore_window_pos_changes_; - // The following factory is used to ignore SetWindowPos() calls for short time - // periods. - base::WeakPtrFactory<HWNDMessageHandler> ignore_pos_changes_factory_; - // The last-seen monitor containing us, and its rect and work area. These are // used to catch updates to the rect and work area and react accordingly. HMONITOR last_monitor_; @@ -457,8 +460,8 @@ class VIEWS_EXPORT HWNDMessageHandler : // to be insufficient. gfx::Rect invalid_rect_; - // A factory that allows us to schedule a redraw for layered windows. - base::WeakPtrFactory<HWNDMessageHandler> paint_layered_window_factory_; + // Set to true when waiting for RedrawLayeredWindowContents(). + bool waiting_for_redraw_layered_window_contents_; // True if we are allowed to update the layered window from the DIB backing // store if necessary. @@ -470,6 +473,9 @@ class VIEWS_EXPORT HWNDMessageHandler : // A factory used to lookup appbar autohide edges. base::WeakPtrFactory<HWNDMessageHandler> autohide_factory_; + // Generates touch-ids for touch-events. + ui::SequentialIDGenerator id_generator_; + DISALLOW_COPY_AND_ASSIGN(HWNDMessageHandler); }; diff --git a/chromium/ui/views/win/hwnd_message_handler_delegate.h b/chromium/ui/views/win/hwnd_message_handler_delegate.h index 58318509051..959822be50e 100644 --- a/chromium/ui/views/win/hwnd_message_handler_delegate.h +++ b/chromium/ui/views/win/hwnd_message_handler_delegate.h @@ -153,6 +153,10 @@ class VIEWS_EXPORT HWNDMessageHandlerDelegate { // Called when the system's work area has changed. virtual void HandleWorkAreaChanged() = 0; + // Called when the window's visibility is changing. |visible| holds the new + // state. + virtual void HandleVisibilityChanging(bool visible) = 0; + // Called when the window's visibility changed. |visible| holds the new state. virtual void HandleVisibilityChanged(bool visible) = 0; @@ -181,9 +185,8 @@ class VIEWS_EXPORT HWNDMessageHandlerDelegate { // translation). Returns true if the event was sent to the input method. virtual bool HandleUntranslatedKeyEvent(const ui::KeyEvent& event) = 0; - // Called when a touch event is received. Returns true if the event was - // handled by the delegate. - virtual bool HandleTouchEvent(const ui::TouchEvent& event) = 0; + // Called when a touch event is received. + virtual void HandleTouchEvent(const ui::TouchEvent& event) = 0; // Called when an IME message needs to be processed by the delegate. Returns // true if the event was handled and no default processing should be diff --git a/chromium/ui/views/window/dialog_client_view.cc b/chromium/ui/views/window/dialog_client_view.cc index d592292ed8f..e03c8a1413d 100644 --- a/chromium/ui/views/window/dialog_client_view.cc +++ b/chromium/ui/views/window/dialog_client_view.cc @@ -6,7 +6,7 @@ #include <algorithm> -#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/views/controls/button/blue_button.h" #include "ui/views/controls/button/label_button.h" #include "ui/views/layout/layout_constants.h" @@ -207,7 +207,7 @@ void DialogClientView::Layout() { } // Layout the row containing the buttons and the extra view. - if (has_dialog_buttons() || extra_view_) { + if (has_dialog_buttons() || ShouldShow(extra_view_)) { bounds.Inset(GetButtonRowInsets()); const int height = GetButtonsAndExtraViewRowHeight(); gfx::Rect row_bounds(bounds.x(), bounds.bottom() - height, @@ -283,6 +283,17 @@ void DialogClientView::ViewHierarchyChanged( } } +void DialogClientView::NativeViewHierarchyChanged() { + FocusManager* focus_manager = GetFocusManager(); + if (focus_manager_ != focus_manager) { + if (focus_manager_) + focus_manager_->RemoveFocusChangeListener(this); + focus_manager_ = focus_manager; + if (focus_manager_) + focus_manager_->AddFocusChangeListener(this); + } +} + //////////////////////////////////////////////////////////////////////////////// // DialogClientView, ButtonListener implementation: diff --git a/chromium/ui/views/window/dialog_client_view.h b/chromium/ui/views/window/dialog_client_view.h index 448eae7b1c7..d780806094c 100644 --- a/chromium/ui/views/window/dialog_client_view.h +++ b/chromium/ui/views/window/dialog_client_view.h @@ -62,6 +62,7 @@ class VIEWS_EXPORT DialogClientView : public ClientView, virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE; virtual void ViewHierarchyChanged( const ViewHierarchyChangedDetails& details) OVERRIDE; + virtual void NativeViewHierarchyChanged() OVERRIDE; // ButtonListener implementation: virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE; @@ -84,6 +85,8 @@ class VIEWS_EXPORT DialogClientView : public ClientView, virtual void ChildVisibilityChanged(View* child) OVERRIDE; private: + FRIEND_TEST_ALL_PREFIXES(DialogClientViewTest, FocusManager); + bool has_dialog_buttons() const { return ok_button_ || cancel_button_; } // Create a dialog button of the appropriate type. diff --git a/chromium/ui/views/window/dialog_client_view_unittest.cc b/chromium/ui/views/window/dialog_client_view_unittest.cc index 9f8c8c4a380..28b001f2d28 100644 --- a/chromium/ui/views/window/dialog_client_view_unittest.cc +++ b/chromium/ui/views/window/dialog_client_view_unittest.cc @@ -4,10 +4,11 @@ #include "base/basictypes.h" #include "base/strings/utf_string_conversions.h" -#include "testing/gtest/include/gtest/gtest.h" #include "ui/base/ui_base_types.h" #include "ui/views/controls/button/label_button.h" #include "ui/views/test/test_views.h" +#include "ui/views/test/views_test_base.h" +#include "ui/views/widget/widget.h" #include "ui/views/window/dialog_client_view.h" #include "ui/views/window/dialog_delegate.h" @@ -37,7 +38,7 @@ class TestDialogClientView : public DialogClientView { DISALLOW_COPY_AND_ASSIGN(TestDialogClientView); }; -class DialogClientViewTest : public testing::Test, +class DialogClientViewTest : public ViewsTestBase, public DialogDelegateView { public: DialogClientViewTest() @@ -51,6 +52,8 @@ class DialogClientViewTest : public testing::Test, dialog_buttons_ = ui::DIALOG_BUTTON_NONE; contents_.reset(new StaticSizedView(gfx::Size(100, 200))); client_view_.reset(new TestDialogClientView(contents_.get(), this)); + + ViewsTestBase::SetUp(); } // DialogDelegateView implementation. @@ -233,4 +236,57 @@ TEST_F(DialogClientViewTest, LayoutWithFootnoteHeightForWidth) { footnote_view->bounds().height()); } +// Test that the DialogClientView's FocusManager is properly updated when the +// DialogClientView belongs to a non top level widget and the widget is +// reparented. The DialogClientView belongs to a non top level widget in the +// case of constrained windows. The constrained window's widget is reparented +// when a browser tab is dragged to a different browser window. +TEST_F(DialogClientViewTest, FocusManager) { + scoped_ptr<Widget> toplevel1(new Widget); + Widget::InitParams toplevel1_params = + CreateParams(Widget::InitParams::TYPE_WINDOW); + toplevel1_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + toplevel1->Init(toplevel1_params); + + scoped_ptr<Widget> toplevel2(new Widget); + Widget::InitParams toplevel2_params = + CreateParams(Widget::InitParams::TYPE_WINDOW); + toplevel2_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + toplevel2->Init(toplevel2_params); + + Widget* dialog = new Widget; + Widget::InitParams dialog_params = + CreateParams(Widget::InitParams::TYPE_WINDOW); + dialog_params.child = true; + dialog_params.delegate = new DialogDelegateView(); + dialog_params.parent = toplevel1->GetNativeView(); + dialog->Init(dialog_params); + + // Test that the FocusManager has been properly set when the DialogClientView + // was parented to |dialog|. + DialogClientView* client_view = + static_cast<DialogClientView*>(dialog->client_view()); + EXPECT_EQ(toplevel1->GetFocusManager(), client_view->focus_manager_); + + // Test that the FocusManager is properly updated when the DialogClientView's + // top level widget is changed. + Widget::ReparentNativeView(dialog->GetNativeView(), NULL); + EXPECT_EQ(NULL, client_view->focus_manager_); + Widget::ReparentNativeView(dialog->GetNativeView(), + toplevel2->GetNativeView()); + EXPECT_EQ(toplevel2->GetFocusManager(), client_view->focus_manager_); + Widget::ReparentNativeView(dialog->GetNativeView(), + toplevel1->GetNativeView()); + EXPECT_NE(toplevel1->GetFocusManager(), toplevel2->GetFocusManager()); + EXPECT_EQ(toplevel1->GetFocusManager(), client_view->focus_manager_); + + // Test that the FocusManager is properly cleared when the DialogClientView is + // removed from |dialog| during the widget's destruction. + client_view->set_owned_by_client(); + scoped_ptr<DialogClientView> owned_client_view(client_view); + toplevel1->CloseNow(); + toplevel2->CloseNow(); + EXPECT_EQ(NULL, owned_client_view->focus_manager_); +} + } // namespace views diff --git a/chromium/ui/views/window/dialog_delegate.cc b/chromium/ui/views/window/dialog_delegate.cc index 9291fc74f78..04fcebbf645 100644 --- a/chromium/ui/views/window/dialog_delegate.cc +++ b/chromium/ui/views/window/dialog_delegate.cc @@ -7,7 +7,6 @@ #include "base/logging.h" #include "grit/ui_strings.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/ui_base_switches_util.h" #include "ui/views/bubble/bubble_border.h" #include "ui/views/bubble/bubble_frame_view.h" #include "ui/views/controls/button/label_button.h" @@ -30,8 +29,8 @@ DialogDelegate::~DialogDelegate() { // static bool DialogDelegate::UseNewStyle() { - return switches::IsNewDialogStyleEnabled() && - Textfield::IsViewsTextfieldEnabled(); + // The new dialog style cannot host native Windows textfield controls. + return Textfield::IsViewsTextfieldEnabled(); } // static @@ -52,12 +51,6 @@ Widget* DialogDelegate::CreateDialogWidget(DialogDelegate* dialog, params.parent = parent; params.top_level = true; widget->Init(params); - if (use_new_style) { -#if defined(USE_AURA) - // TODO(msw): Add a matching shadow type and remove the bubble frame border? - corewm::SetShadowType(widget->GetNativeWindow(), corewm::SHADOW_TYPE_NONE); -#endif - } return widget; } @@ -199,6 +192,10 @@ NonClientFrameView* DialogDelegate::CreateNewStyleFrameView( } if (force_opaque_border) widget->set_frame_type(views::Widget::FRAME_TYPE_FORCE_CUSTOM); +#if defined(USE_AURA) + // TODO(msw): Add a matching shadow type and remove the bubble frame border? + corewm::SetShadowType(widget->GetNativeWindow(), corewm::SHADOW_TYPE_NONE); +#endif return frame; } diff --git a/chromium/ui/views/window/frame_buttons.h b/chromium/ui/views/window/frame_buttons.h new file mode 100644 index 00000000000..d534356754d --- /dev/null +++ b/chromium/ui/views/window/frame_buttons.h @@ -0,0 +1,19 @@ +// 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. + +#ifndef UI_VIEWS_WINDOW_FRAME_BUTTONS_H_ +#define UI_VIEWS_WINDOW_FRAME_BUTTONS_H_ + +namespace views { + +// Identifies what a button in a window frame is. +enum FrameButton { + FRAME_BUTTON_MINIMIZE, + FRAME_BUTTON_MAXIMIZE, + FRAME_BUTTON_CLOSE +}; + +} // namespace views + +#endif // UI_VIEWS_WINDOW_FRAME_BUTTONS_H_ diff --git a/chromium/ui/webui/resources/css/apps/common.css b/chromium/ui/webui/resources/css/apps/common.css new file mode 100644 index 00000000000..4f3ef31745d --- /dev/null +++ b/chromium/ui/webui/resources/css/apps/common.css @@ -0,0 +1,169 @@ +/* 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. */ + +button.white-button, +button.blue-button { + border: 5px solid transparent; + box-sizing: content-box; + cursor: default; + height: 21px; + line-height: 21px; + margin: 0; + min-height: 21px; + min-width: 55px; + padding: 0 10px; + position: relative; + outline: none; + text-align: center; + z-index: 1; +} + +button.white-button { + border-image: -webkit-image-set( + url('chrome://resources/images/apps/button.png') 1x, + url('chrome://resources/images/2x/apps/button.png') + 2x) 5 fill / 5px / 2px repeat; +} + +button.white-button:hover { + border-image: -webkit-image-set( + url('chrome://resources/images/apps/button_hover.png') 1x, + url('chrome://resources/images/2x/apps/button_hover.png') + 2x) 5 fill / 5px / 2px repeat; +} + +button.white-button:active { + border-image: -webkit-image-set( + url('chrome://resources/images/apps/button_pressed.png') 1x, + url('chrome://resources/images/2x/apps/button_pressed.png') + 2x) 5 fill / 5px / 2px repeat; +} + +button.white-button:focus { + border-image: -webkit-image-set( + url('chrome://resources/images/apps/button_focused.png') 1x, + url('chrome://resources/images/2x/apps/button_focused.png') + 2x) 5 fill / 5px / 2px repeat; +} + +button.white-button:focus:hover { + border-image: -webkit-image-set( + url('chrome://resources/images/apps/button_focused_hover.png') 1x, + url('chrome://resources/images/2x/apps/button_focused_hover.png') + 2x) 5 fill / 5px / 2px repeat; +} + +button.white-button:focus:active { + border-image: -webkit-image-set( + url('chrome://resources/images/apps/button_focused_pressed.png') 1x, + url('chrome://resources/images/2x/apps/button_focused_pressed.png') + 2x) 5 fill / 5px / 2px repeat; +} + +button.white-button[disabled] { + border-image: -webkit-image-set( + url('chrome://resources/images/apps/button_inactive.png') 1x, + url('chrome://resources/images/2x/apps/button_inactive.png') + 2x) 5 fill / 5px / 2px repeat; +} + +button.blue-button { + border-image: -webkit-image-set( + url('chrome://resources/images/apps/blue_button.png') 1x, + url('chrome://resources/images/2x/apps/blue_button.png') + 2x) 5 fill / 5px / 2px repeat; +} + +button.blue-button:hover { + border-image: -webkit-image-set( + url('chrome://resources/images/apps/blue_button_hover.png') 1x, + url('chrome://resources/images/2x/apps/blue_button_hover.png') + 2x) 5 fill / 5px / 2px repeat; +} + +button.blue-button:active { + border-image: -webkit-image-set( + url('chrome://resources/images/apps/blue_button_pressed.png') 1x, + url('chrome://resources/images/2x/apps/blue_button_pressed.png') + 2x) 5 fill / 5px / 2px repeat; +} + +button.blue-button:focus { + border-image: -webkit-image-set( + url('chrome://resources/images/apps/blue_button_focused.png') 1x, + url('chrome://resources/images/2x/apps/blue_button_focused.png') + 2x) 5 fill / 5px / 2px repeat; +} + +button.blue-button:focus:hover { + border-image: -webkit-image-set( + url('chrome://resources/images/apps/blue_button_focused_hover.png') 1x, + url('chrome://resources/images/2x/apps/blue_button_focused_hover.png') + 2x) 5 fill / 5px / 2px repeat; +} + +button.blue-button:focus:active { + border-image: -webkit-image-set( + url('chrome://resources/images/apps/blue_button_focused_pressed.png') 1x, + url('chrome://resources/images/2x/apps/blue_button_focused_pressed.png') + 2x) 5 fill / 5px / 2px repeat; +} + +button.blue-button[disabled] { + border-image: -webkit-image-set( + url('chrome://resources/images/apps/blue_button_inactive.png') 1x, + url('chrome://resources/images/2x/apps/blue_button_inactive.png') + 2x) 5 fill / 5px / 2px repeat; +} + +input[type='checkbox'] { + -webkit-appearance: none; + border: none; + outline: none; +} + +input[type='checkbox']::after { + content: ''; + display: block; + height: 16px; + left: -2px; + top: -2px; + width: 16px; +} + +input[type='checkbox']:not(:checked)::after { + background-image: -webkit-image-set( + url('chrome://resources/images/apps/checkbox.png') 1x, + url('chrome://resources/images/2x/apps/checkbox.png') 2x); +} + +input[type='checkbox']:focus:not(:checked)::after { + background-image: -webkit-image-set( + url('chrome://resources/images/apps/checkbox_focused.png') 1x, + url('chrome://resources/images/2x/apps/checkbox_focused.png') 2x); +} + +input[type='checkbox']:disabled:not(:checked)::after { + background-image: -webkit-image-set( + url('chrome://resources/images/apps/checkbox_inactive.png') 1x, + url('chrome://resources/images/2x/apps/checkbox_inactive.png') 2x); +} + +input[type='checkbox']:checked::after { + background-image: -webkit-image-set( + url('chrome://resources/images/apps/checkbox_checked.png') 1x, + url('chrome://resources/images/2x/apps/checkbox_checked.png') 2x); +} + +input[type='checkbox']:focus:checked::after { + background-image: -webkit-image-set( + url('chrome://resources/images/apps/checkbox_focused_checked.png') 1x, + url('chrome://resources/images/2x/apps/checkbox_focused_checked.png') 2x); +} + +input[type='checkbox']:disabled:checked::after { + background-image: -webkit-image-set( + url('chrome://resources/images/apps/checkbox_checked_inactive.png') 1x, + url('chrome://resources/images/2x/apps/checkbox_checked_inactive.png') 2x); +} diff --git a/chromium/ui/webui/resources/css/apps/topbutton_bar.css b/chromium/ui/webui/resources/css/apps/topbutton_bar.css new file mode 100644 index 00000000000..35641e9d4b8 --- /dev/null +++ b/chromium/ui/webui/resources/css/apps/topbutton_bar.css @@ -0,0 +1,61 @@ +/* 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. */ + +.topbutton-bar { + -webkit-box-align: center; + display: -webkit-box; +} + +.topbutton-bar button { + -webkit-app-region: no-drag; + -webkit-box-shadow: none; + -webkit-margin-end: 10px; + background-color: transparent; + background-image: none; + background-position: center; + background-repeat: no-repeat; + border: 0; + display: block; + height: 32px; + min-width: 0; + outline: none; + padding: 0; + width: 32px; +} + +.topbutton-bar button:active { + -webkit-box-shadow: + 0 1px 0 0 #c2c2c2 inset, + 0 0 0 1px #dedede inset; +} + +.topbutton-bar button:hover, +.topbutton-bar button:focus, +.topbutton-bar button:active { + background-color: #ededed; +} + +.topbutton-bar .maximize-button { + background-image: -webkit-image-set( + url('chrome://resources/images/apps/topbar_button_maximize.png') 1x, + url('chrome://resources/images/2x/apps/topbar_button_maximize.png') 2x); +} + +.topbutton-bar .minimize-button { + background-image: -webkit-image-set( + url('chrome://resources/images/apps/topbar_button_minimize.png') 1x, + url('chrome://resources/images/2x/apps/topbar_button_minimize.png') 2x); +} + +.topbutton-bar .close-button { + background-image: -webkit-image-set( + url('chrome://resources/images/apps/topbar_button_close.png') 1x, + url('chrome://resources/images/2x/apps/topbar_button_close.png') 2x); +} + +.topbutton-bar .gear-button { + background-image: -webkit-image-set( + url('chrome://resources/images/apps/topbar_button_settings.png') 1x, + url('chrome://resources/images/2x/apps/topbar_button_settings.png') 2x); +} diff --git a/chromium/ui/webui/resources/css/overlay.css b/chromium/ui/webui/resources/css/overlay.css index af47453698c..5bf914cff52 100644 --- a/chromium/ui/webui/resources/css/overlay.css +++ b/chromium/ui/webui/resources/css/overlay.css @@ -151,7 +151,7 @@ html[dir='rtl'] .overlay .page .action-area { /* On OSX 10.7, hidden scrollbars may prevent the user from realizing that the * overlay contains scrollable content. To resolve this, style the scrollbars on * OSX so they are always visible. See http://crbug.com/123010. */ -<if expr="is_macosx"> +<if expr="is_macosx or is_ios"> .overlay .page .content-area::-webkit-scrollbar { -webkit-appearance: none; width: 11px; diff --git a/chromium/ui/webui/resources/css/tree.css b/chromium/ui/webui/resources/css/tree.css index 64ae2126e27..3bd08f7019e 100644 --- a/chromium/ui/webui/resources/css/tree.css +++ b/chromium/ui/webui/resources/css/tree.css @@ -169,7 +169,7 @@ tree[icon-visibility=parent] .tree-row[has-children=false] > .tree-label { font-size: inherit; font-weight: inherit; margin: -2px -8px -2px -3px; -<if expr="not is_macosx"> +<if expr="not is_macosx and not is_ios"> outline: none; </if> padding: 1px 7px 1px 1px; diff --git a/chromium/ui/webui/resources/css/widgets.css b/chromium/ui/webui/resources/css/widgets.css index 5a69ea8ec13..68b7c26bc94 100644 --- a/chromium/ui/webui/resources/css/widgets.css +++ b/chromium/ui/webui/resources/css/widgets.css @@ -98,7 +98,7 @@ textarea { /* Use min-height to accommodate addditional padding for touch as needed. */ min-height: 2em; padding: 3px; -<if expr="is_win or is_macosx"> +<if expr="is_win or is_macosx or is_ios"> /* For better alignment between adjacent buttons and inputs. */ padding-bottom: 4px; </if> diff --git a/chromium/ui/webui/resources/images/2x/apps/button_butter_bar_close.png b/chromium/ui/webui/resources/images/2x/apps/button_butter_bar_close.png Binary files differnew file mode 100644 index 00000000000..260af771e93 --- /dev/null +++ b/chromium/ui/webui/resources/images/2x/apps/button_butter_bar_close.png diff --git a/chromium/ui/webui/resources/images/2x/apps/button_butter_bar_close_hover.png b/chromium/ui/webui/resources/images/2x/apps/button_butter_bar_close_hover.png Binary files differnew file mode 100644 index 00000000000..03e9b12f675 --- /dev/null +++ b/chromium/ui/webui/resources/images/2x/apps/button_butter_bar_close_hover.png diff --git a/chromium/ui/webui/resources/images/2x/apps/button_butter_bar_close_pressed.png b/chromium/ui/webui/resources/images/2x/apps/button_butter_bar_close_pressed.png Binary files differnew file mode 100644 index 00000000000..4f31f86ec12 --- /dev/null +++ b/chromium/ui/webui/resources/images/2x/apps/button_butter_bar_close_pressed.png diff --git a/chromium/ui/webui/resources/images/apps/button_butter_bar_close.png b/chromium/ui/webui/resources/images/apps/button_butter_bar_close.png Binary files differnew file mode 100644 index 00000000000..b9143c3d676 --- /dev/null +++ b/chromium/ui/webui/resources/images/apps/button_butter_bar_close.png diff --git a/chromium/ui/webui/resources/images/apps/button_butter_bar_close_hover.png b/chromium/ui/webui/resources/images/apps/button_butter_bar_close_hover.png Binary files differnew file mode 100644 index 00000000000..02e91dbf180 --- /dev/null +++ b/chromium/ui/webui/resources/images/apps/button_butter_bar_close_hover.png diff --git a/chromium/ui/webui/resources/images/apps/button_butter_bar_close_pressed.png b/chromium/ui/webui/resources/images/apps/button_butter_bar_close_pressed.png Binary files differnew file mode 100644 index 00000000000..470271a0236 --- /dev/null +++ b/chromium/ui/webui/resources/images/apps/button_butter_bar_close_pressed.png diff --git a/chromium/ui/webui/resources/images/guest_icon_standalone.png b/chromium/ui/webui/resources/images/guest_icon_standalone.png Binary files differdeleted file mode 100644 index c4d29bcb6b3..00000000000 --- a/chromium/ui/webui/resources/images/guest_icon_standalone.png +++ /dev/null diff --git a/chromium/ui/webui/resources/images/question_mark.png b/chromium/ui/webui/resources/images/question_mark.png Binary files differnew file mode 100644 index 00000000000..994056b93be --- /dev/null +++ b/chromium/ui/webui/resources/images/question_mark.png diff --git a/chromium/ui/webui/resources/js/cr.js b/chromium/ui/webui/resources/js/cr.js index 2a7ab7823b4..3ea3b91dd8a 100644 --- a/chromium/ui/webui/resources/js/cr.js +++ b/chromium/ui/webui/resources/js/cr.js @@ -280,21 +280,26 @@ this.cr = (function() { }; } + var OriginalEvent = global.Event; + /** * Creates a new event to be used with cr.EventTarget or DOM EventTarget * objects. * @param {string} type The name of the event. * @param {boolean=} opt_bubbles Whether the event bubbles. * Default is false. - * @param {boolean=} opt_preventable Whether the default action of the event - * can be prevented. + * @param {boolean=} opt_cancelable Whether the default action of the event + * can be prevented. Unlike the DOM event constructor, this defaults to + * true. * @constructor * @extends {Event} */ - function Event(type, opt_bubbles, opt_preventable) { - var e = cr.doc.createEvent('Event'); - e.initEvent(type, !!opt_bubbles, !!opt_preventable); - e.__proto__ = global.Event.prototype; + function Event(type, opt_bubbles, opt_cancelable) { + var e = new OriginalEvent(type, { + bubbles: opt_bubbles, + cancelable: opt_cancelable === undefined ? true : opt_cancelable + }); + e.__proto__ = OriginalEvent.prototype; return e; }; @@ -319,7 +324,7 @@ this.cr = (function() { return; } - Event.prototype = {__proto__: global.Event.prototype}; + Event.prototype = {__proto__: OriginalEvent.prototype}; cr.doc = document; diff --git a/chromium/ui/webui/resources/js/cr/event_target.js b/chromium/ui/webui/resources/js/cr/event_target.js index 5bcb41d6138..d9bc681c75f 100644 --- a/chromium/ui/webui/resources/js/cr/event_target.js +++ b/chromium/ui/webui/resources/js/cr/event_target.js @@ -76,9 +76,6 @@ cr.define('cr', function() { event.__defineGetter__('target', function() { return self; }); - event.preventDefault = function() { - this.returnValue = false; - }; var type = event.type; var prevented = 0; @@ -93,7 +90,7 @@ cr.define('cr', function() { } } - return !prevented && event.returnValue; + return !prevented && !event.defaultPrevented; } }; diff --git a/chromium/ui/webui/resources/js/cr/ui/context_menu_button.js b/chromium/ui/webui/resources/js/cr/ui/context_menu_button.js index 88dd605d380..7d324e3ce0f 100644 --- a/chromium/ui/webui/resources/js/cr/ui/context_menu_button.js +++ b/chromium/ui/webui/resources/js/cr/ui/context_menu_button.js @@ -67,6 +67,20 @@ cr.define('cr.ui', function() { break; } MenuButton.prototype.handleEvent.call(this, e); + }, + + /** + * Override MenuButton showMenu to allow the mousedown to be fully handled + * before the menu is shown. This is important in case the mousedown + * triggers command changes. + * @param {boolean} shouldSetFocus Whether the menu should be focused after + * the menu is shown. + */ + showMenu: function(shouldSetFocus) { + var self = this; + window.setTimeout(function() { + MenuButton.prototype.showMenu.call(self, shouldSetFocus); + }); } }; diff --git a/chromium/ui/webui/resources/js/cr/ui/list.js b/chromium/ui/webui/resources/js/cr/ui/list.js index 080aa9c23b8..a094834f637 100644 --- a/chromium/ui/webui/resources/js/cr/ui/list.js +++ b/chromium/ui/webui/resources/js/cr/ui/list.js @@ -1126,6 +1126,10 @@ cr.define('cr.ui', function() { this.afterFiller_.style.height = afterFillerHeight + 'px'; + // Restores the number of pixels scrolled, since it might be changed while + // DOM operations. + this.scrollTop = scrollTop; + // We don't set the lead or selected properties until after adding all // items, in case they force relayout in response to these events. var listItem = null; diff --git a/chromium/ui/webui/resources/js/util.js b/chromium/ui/webui/resources/js/util.js index e7beb676f40..bec9c3b4dec 100644 --- a/chromium/ui/webui/resources/js/util.js +++ b/chromium/ui/webui/resources/js/util.js @@ -302,3 +302,23 @@ function createElementWithClassName(type, className) { elm.className = className; return elm; } + +/** + * webkitTransitionEnd does not always fire (e.g. when animation is aborted + * or when no paint happens during the animation). This function sets up + * a timer and emulate the event if it is not fired when the timer expires. + * @param {!HTMLElement} el The element to watch for webkitTransitionEnd. + * @param {number} timeOut The maximum wait time in milliseconds for the + * webkitTransitionEnd to happen. + */ +function ensureTransitionEndEvent(el, timeOut) { + var fired = false; + el.addEventListener('webkitTransitionEnd', function f(e) { + el.removeEventListener('webkitTransitionEnd', f); + fired = true; + }); + window.setTimeout(function() { + if (!fired) + cr.dispatchSimpleEvent(el, 'webkitTransitionEnd'); + }, timeOut); +} diff --git a/chromium/ui/webui/resources/js/webui_resource_test.js b/chromium/ui/webui/resources/js/webui_resource_test.js new file mode 100644 index 00000000000..cce993d7af1 --- /dev/null +++ b/chromium/ui/webui/resources/js/webui_resource_test.js @@ -0,0 +1,204 @@ +// 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. + +/** + * Tests that an observation matches the expected value. + * @param {Object} expected The expected value. + * @param {Object} observed The actual value. + * @param {string=} opt_message Optional message to include with a test + * failure. + */ +function assertEquals(expected, observed, opt_message) { + if (observed !== expected) { + var message = 'Assertion Failed\n Observed: ' + observed + + '\n Expected: ' + expected; + if (opt_message) + message = message + '\n ' + opt_message; + throw new Error(message); + } +} + +/** + * Verifies that a test result is true. + * @param {boolean} observed The observed value. + * @param {string=} opt_message Optional message to include with a test + * failure. + */ +function assertTrue(observed, opt_message) { + assertEquals(true, observed, opt_message); +} + +/** + * Verifies that a test result is false. + * @param {boolean} observed The observed value. + * @param {string=} opt_message Optional message to include with a test + * failure. + */ +function assertFalse(observed, opt_message) { + assertEquals(false, observed, opt_message); +} + +/** + * Verifies that the observed and reference values differ. + * @param {Object} reference The target value for comparison. + * @param {Object} observed The test result. + * @param {string=} opt_message Optional message to include with a test + * failure. + */ +function assertNotEqual(reference, observed, opt_message) { + if (observed === reference) { + var message = 'Assertion Failed\n Observed: ' + observed + + '\n Reference: ' + reference; + if (opt_message) + message = message + '\n ' + opt_message; + throw new Error(message); + } +} + +/** + * Verifies that a test evaluation results in an exception. + * @param {!Function} f The test function. + */ +function assertThrows(f) { + var triggeredError = false; + try { + f(); + } catch(err) { + triggeredError = true; + } + if (!triggeredError) + throw new Error('Assertion Failed: throw expected.'); +} + +/** + * Verifies that the contents of the expected and observed arrays match. + * @param {!Array} expected The expected result. + * @param {!Array} observed The actual result. + */ +function assertArrayEquals(expected, observed) { + var v1 = Array.prototype.slice.call(expected); + var v2 = Array.prototype.slice.call(observed); + var equal = v1.length == v2.length; + if (equal) { + for (var i = 0; i < v1.length; i++) { + if (v1[i] !== v2[i]) { + equal = false; + break; + } + } + } + if (!equal) { + var message = + ['Assertion Failed', 'Observed: ' + v2, 'Expected: ' + v1].join('\n '); + throw new Error(message); + } +} + +/** + * Verifies that the expected and observed result have the same content. + * @param {*} expected The expected result. + * @param {*} observed The actual result. + */ +function assertDeepEquals(expected, observed, opt_message) { + if (typeof expected == 'object' && expected != null) { + assertNotEqual(null, observed); + for (var key in expected) { + assertTrue(key in observed, opt_message); + assertDeepEquals(expected[key], observed[key], opt_message); + } + for (var key in observed) { + assertTrue(key in expected, opt_message); + } + } else { + assertEquals(expected, observed, opt_message); + } +} + +/** + * Defines runTests. + */ +(function(exports) { + /** + * List of test cases. + * @type {Array.<string>} List of function names for tests to run. + */ + var testCases = []; + + /** + * Indicates if all tests have run successfully. + * @type {boolean} + */ + var cleanTestRun = true; + + /** + * Armed during setup of a test to call the matching tear down code. + * @type {Function} + */ + var pendingTearDown = null; + + /** + * Runs all functions starting with test and reports success or + * failure of the test suite. + */ + function runTests() { + for (var name in window) { + if (typeof window[name] == 'function' && /^test/.test(name)) + testCases.push(name); + } + if (!testCases.length) { + console.error('Failed to find test cases.'); + cleanTestRun = false; + } + continueTesting(); + } + + /** + * Runs the next test in the queue. Reports the test results if the queue is + * empty. + */ + function continueTesting() { + if (pendingTearDown) { + pendingTearDown(); + pendingTearDown = null; + } + if (testCases.length > 0) { + var fn = testCases.pop(); + var isAsyncTest = window[fn].length; + try { + if (window.setUp) + window.setUp(); + pendingTearDown = window.tearDown; + window[fn](continueTesting); + } catch(err) { + console.error('Failure in test ' + fn + '\n' + err); + console.log(err.stack); + cleanTestRun = false; + } + // Asynchronous tests must manually call continueTesting when complete. + if (!isAsyncTest) + continueTesting(); + } else { + endTests(cleanTestRun); + } + if (testCases.length) { + domAutomationController.setAutomationId(1); + domAutomationController.send('PENDING'); + } + }; + + exports.runTests = runTests; +})(this); + +/** + * Signals completion of a test. + * @param {boolean} success Indicates if the test completed successfully. + */ +function endTests(success) { + domAutomationController.setAutomationId(1); + domAutomationController.send(success ? 'SUCCESS' : 'FAILURE'); +} + +window.onerror = function() { + endTests(false); +}; diff --git a/chromium/ui/webui/resources/webui_resources.grd b/chromium/ui/webui/resources/webui_resources.grd index 219ebbf1597..7cc6c7c47d1 100644 --- a/chromium/ui/webui/resources/webui_resources.grd +++ b/chromium/ui/webui/resources/webui_resources.grd @@ -17,6 +17,162 @@ without changes to the corresponding grd file. --> <include name="IDR_WEBUI_I18N_TEMPLATE_JS" file="js/i18n_template.js" type="BINDATA" /> <include name="IDR_WEBUI_I18N_TEMPLATE2_JS" file="js/i18n_template2.js" flattenhtml="true" type="BINDATA" /> <include name="IDR_WEBUI_JSTEMPLATE_JS" file="js/jstemplate_compiled.js" flattenhtml="true" type="BINDATA" /> + + <!-- Component apps common image resources - 1x --> + <!-- White button --> + <include name="IDR_WEBUI_IMAGES_APPS_BUTTON" + file="../../resources/default_100_percent/common/button.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BUTTON_PRESSED" + file="../../resources/default_100_percent/common/button_pressed.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BUTTON_HOVER" + file="../../resources/default_100_percent/common/button_hover.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BUTTON_DISABLED" + file="../../resources/default_100_percent/common/button_inactive.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BUTTON_FOCUSED" + file="../../resources/default_100_percent/common/button_focused.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BUTTON_FOCUSED_PRESSED" + file="../../resources/default_100_percent/common/button_focused_pressed.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BUTTON_FOCUSED_HOVER" + file="../../resources/default_100_percent/common/button_focused_hover.png" type="BINDATA" /> + <!-- Blue button --> + <include name="IDR_WEBUI_IMAGES_APPS_BLUE_BUTTON" + file="../../resources/default_100_percent/common/blue_button.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BLUE_BUTTON_PRESSED" + file="../../resources/default_100_percent/common/blue_button_pressed.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BLUE_BUTTON_HOVER" + file="../../resources/default_100_percent/common/blue_button_hover.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BLUE_BUTTON_DISABLED" + file="../../resources/default_100_percent/common/blue_button_inactive.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BLUE_BUTTON_FOCUSED" + file="../../resources/default_100_percent/common/blue_button_focused.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BLUE_BUTTON_FOCUSED_PRESSED" + file="../../resources/default_100_percent/common/blue_button_focused_pressed.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BLUE_BUTTON_FOCUSED_HOVER" + file="../../resources/default_100_percent/common/blue_button_focused_hover.png" type="BINDATA" /> + <!-- Checkbox (unchecked) --> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX" + file="../../resources/default_100_percent/common/checkbox.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_HOVER" + file="../../resources/default_100_percent/common/checkbox_hover.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_PRESSED" + file="../../resources/default_100_percent/common/checkbox_pressed.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_FOCUSED" + file="../../resources/default_100_percent/common/checkbox_focused.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_FOCUSED_HOVER" + file="../../resources/default_100_percent/common/checkbox_focused_hover.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_FOCUSED_PRESSED" + file="../../resources/default_100_percent/common/checkbox_focused_pressed.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_INACTIVE" + file="../../resources/default_100_percent/common/checkbox_inactive.png" type="BINDATA" /> + <!-- Checkbox (checked) --> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_CHECKED" + file="../../resources/default_100_percent/common/checkbox_checked.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_CHECKED_HOVER" + file="../../resources/default_100_percent/common/checkbox_checked_hover.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_CHECKED_PRESSED" + file="../../resources/default_100_percent/common/checkbox_checked_pressed.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_FOCUSED_CHECKED" + file="../../resources/default_100_percent/common/checkbox_focused_checked.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_FOCUSED_CHECKED_HOVER" + file="../../resources/default_100_percent/common/checkbox_focused_checked_hover.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_FOCUSED_CHECKED_PRESSED" + file="../../resources/default_100_percent/common/checkbox_focused_checked_pressed.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_CHECKED_INACTIVE" + file="../../resources/default_100_percent/common/checkbox_checked_inactive.png" type="BINDATA" /> + <!-- Misc buttons --> + <include name="IDR_WEBUI_IMAGES_APPS_TOPBAR_BUTTON_CLOSE" + file="images/apps/topbar_button_close.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_TOPBAR_BUTTON_MAXIMIZE" + file="images/apps/topbar_button_maximize.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_TOPBAR_BUTTON_MINIMIZE" + file="images/apps/topbar_button_minimize.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_TOPBAR_BUTTON_SETTINGS" + file="images/apps/topbar_button_settings.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BUTTON_BUTTER_BAR_CLOSE" + file="images/apps/button_butter_bar_close.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BUTTON_BUTTER_BAR_CLOSE_HOVER" + file="images/apps/button_butter_bar_close_hover.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BUTTON_BUTTER_BAR_CLOSE_PRESSED" + file="images/apps/button_butter_bar_close_pressed.png" type="BINDATA" /> + + <!-- Component apps common image resources - 2x --> + <!-- White button --> + <include name="IDR_WEBUI_IMAGES_APPS_BUTTON_2X" + file="../../resources/default_200_percent/common/button.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BUTTON_2X_PRESSED" + file="../../resources/default_200_percent/common/button_pressed.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BUTTON_2X_HOVER" + file="../../resources/default_200_percent/common/button_hover.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BUTTON_2X_DISABLED" + file="../../resources/default_200_percent/common/button_inactive.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BUTTON_2X_FOCUSED" + file="../../resources/default_200_percent/common/button_focused.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BUTTON_2X_FOCUSED_PRESSED" + file="../../resources/default_200_percent/common/button_focused_pressed.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BUTTON_2X_FOCUSED_HOVER" + file="../../resources/default_200_percent/common/button_focused_hover.png" type="BINDATA" /> + <!-- Blue button --> + <include name="IDR_WEBUI_IMAGES_APPS_BLUE_BUTTON_2X" + file="../../resources/default_200_percent/common/blue_button.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BLUE_BUTTON_2X_PRESSED" + file="../../resources/default_200_percent/common/blue_button_pressed.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BLUE_BUTTON_2X_HOVER" + file="../../resources/default_200_percent/common/blue_button_hover.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BLUE_BUTTON_2X_DISABLED" + file="../../resources/default_200_percent/common/blue_button_inactive.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BLUE_BUTTON_2X_FOCUSED" + file="../../resources/default_200_percent/common/blue_button_focused.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BLUE_BUTTON_2X_FOCUSED_PRESSED" + file="../../resources/default_200_percent/common/blue_button_focused_pressed.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BLUE_BUTTON_2X_FOCUSED_HOVER" + file="../../resources/default_200_percent/common/blue_button_focused_hover.png" type="BINDATA" /> + <!-- Checkbox (unchecked) --> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_2X" + file="../../resources/default_200_percent/common/checkbox.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_2X_HOVER" + file="../../resources/default_200_percent/common/checkbox_hover.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_2X_PRESSED" + file="../../resources/default_200_percent/common/checkbox_pressed.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_2X_FOCUSED" + file="../../resources/default_200_percent/common/checkbox_focused.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_2X_FOCUSED_HOVER" + file="../../resources/default_200_percent/common/checkbox_focused_hover.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_2X_FOCUSED_PRESSED" + file="../../resources/default_200_percent/common/checkbox_focused_pressed.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_INACTIVE_2X" + file="../../resources/default_200_percent/common/checkbox_inactive.png" type="BINDATA" /> + <!-- Checkbox (checked) --> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_CHECKED_2X" + file="../../resources/default_200_percent/common/checkbox_checked.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_CHECKED_2X_HOVER" + file="../../resources/default_200_percent/common/checkbox_checked_hover.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_CHECKED_2X_PRESSED" + file="../../resources/default_200_percent/common/checkbox_checked_pressed.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_FOCUSED_CHECKED_2X" + file="../../resources/default_200_percent/common/checkbox_focused_checked.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_FOCUSED_CHECKED_2X_HOVER" + file="../../resources/default_200_percent/common/checkbox_focused_checked_hover.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_FOCUSED_CHECKED_2X_PRESSED" + file="../../resources/default_200_percent/common/checkbox_focused_checked_pressed.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_CHECKBOX_CHECKED_INACTIVE_2X" + file="../../resources/default_200_percent/common/checkbox_checked_inactive.png" type="BINDATA" /> + <!-- Misc buttons --> + <include name="IDR_WEBUI_IMAGES_APPS_TOPBAR_BUTTON_2X_CLOSE" + file="images/2x/apps/topbar_button_close.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_TOPBAR_BUTTON_2X_MAXIMIZE" + file="images/2x/apps/topbar_button_maximize.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_TOPBAR_BUTTON_2X_MINIMIZE" + file="images/2x/apps/topbar_button_minimize.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_TOPBAR_BUTTON_2X_SETTINGS" + file="images/2x/apps/topbar_button_settings.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BUTTON_BUTTER_BAR_CLOSE_2X" + file="images/2x/apps/button_butter_bar_close.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BUTTON_BUTTER_BAR_CLOSE_HOVER_2X" + file="images/2x/apps/button_butter_bar_close_hover.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_APPS_BUTTON_BUTTER_BAR_CLOSE_PRESSED_2X" + file="images/2x/apps/button_butter_bar_close_pressed.png" type="BINDATA" /> + + <!-- Non-apps images --> <include name="IDR_WEBUI_IMAGES_CHECK" file="images/check.png" type="BINDATA" /> <include name="IDR_WEBUI_IMAGES_CHECKBOX_BLACK" @@ -31,6 +187,8 @@ without changes to the corresponding grd file. --> file="images/google-transparent.png" type="BINDATA" /> <include name="IDR_WEBUI_IMAGES_HELP" file="images/help.png" type="BINDATA" /> + <include name="IDR_WEBUI_IMAGES_QUESTION_MARK" + file="images/question_mark.png" type="BINDATA" /> <include name="IDR_WEBUI_IMAGES_SELECT" file="images/select.png" type="BINDATA" /> <include name="IDR_WEBUI_IMAGES_SPINNER" @@ -51,6 +209,10 @@ without changes to the corresponding grd file. --> file="css/bubble_button.css" type="chrome_html" /> <structure name="IDR_WEBUI_CSS_BUTTER_BAR" file="css/butter_bar.css" type="chrome_html" /> + <structure name="IDR_WEBUI_CSS_APPS_COMMON" + file="css/apps/common.css" type="chrome_html" /> + <structure name="IDR_WEBUI_CSS_APPS_TOPBUTTON_BAR" + file="css/apps/topbutton_bar.css" type="chrome_html" /> <structure name="IDR_WEBUI_CSS_DIALOGS" file="css/dialogs.css" type="chrome_html" /> <structure name="IDR_WEBUI_CSS_LIST" @@ -204,6 +366,8 @@ without changes to the corresponding grd file. --> file="js/parse_html_subset.js" type="chrome_html" /> <structure name="IDR_WEBUI_JS_UTIL" file="js/util.js" type="chrome_html" flattenhtml="true" /> + <structure name="IDR_WEBUI_JS_WEBUI_RESOURCE_TEST" + file="js/webui_resource_test.js" type="chrome_html" /> <if expr="pp_ifdef('chromeos')"> <structure name="IDR_WEBUI_CSS_UI_ACCOUNT_TWEAKS" file="css/chromeos/ui_account_tweaks.css" diff --git a/chromium/ui/webui/web_ui_util.cc b/chromium/ui/webui/web_ui_util.cc index 44108f759ea..e171da85b4f 100644 --- a/chromium/ui/webui/web_ui_util.cc +++ b/chromium/ui/webui/web_ui_util.cc @@ -79,12 +79,12 @@ bool ParseScaleFactor(const base::StringPiece& identifier, ui::ScaleFactor* scale_factor) { *scale_factor = ui::SCALE_FACTOR_100P; if (identifier.empty()) { - LOG(ERROR) << "Invalid scale factor format: " << identifier; + LOG(WARNING) << "Invalid scale factor format: " << identifier; return false; } if (*identifier.rbegin() != 'x') { - LOG(ERROR) << "Invalid scale factor format: " << identifier; + LOG(WARNING) << "Invalid scale factor format: " << identifier; return false; } @@ -92,7 +92,7 @@ bool ParseScaleFactor(const base::StringPiece& identifier, std::string stripped; identifier.substr(0, identifier.length() - 1).CopyToString(&stripped); if (!base::StringToDouble(stripped, &scale)) { - LOG(ERROR) << "Invalid scale factor format: " << identifier; + LOG(WARNING) << "Invalid scale factor format: " << identifier; return false; } |