Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(24)

Unified Diff: ui/base/test/ui_controls_mac.mm

Issue 851853002: It is time. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Trying to reup because the last upload failed. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/base/test/ui_controls_internal_win.cc ('k') | ui/base/test/ui_controls_win.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/base/test/ui_controls_mac.mm
diff --git a/ui/base/test/ui_controls_mac.mm b/ui/base/test/ui_controls_mac.mm
deleted file mode 100644
index cf2c239de39e9595434a014e32b9e6f62b9f41bd..0000000000000000000000000000000000000000
--- a/ui/base/test/ui_controls_mac.mm
+++ /dev/null
@@ -1,396 +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.
-
-#include "ui/base/test/ui_controls.h"
-
-#import <Cocoa/Cocoa.h>
-#include <mach/mach_time.h>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/message_loop/message_loop.h"
-#include "ui/events/keycodes/keyboard_code_conversion_mac.h"
-
-
-// Implementation details: We use [NSApplication sendEvent:] instead
-// of [NSApplication postEvent:atStart:] so that the event gets sent
-// immediately. This lets us run the post-event task right
-// immediately as well. Unfortunately I cannot subclass NSEvent (it's
-// probably a class cluster) to allow other easy answers. For
-// example, if I could subclass NSEvent, I could run the Task in it's
-// dealloc routine (which necessarily happens after the event is
-// dispatched). Unlike Linux, Mac does not have message loop
-// observer/notification. Unlike windows, I cannot post non-events
-// into the event queue. (I can post other kinds of tasks but can't
-// guarantee their order with regards to events).
-
-// But [NSApplication sendEvent:] causes a problem when sending mouse click
-// events. Because in order to handle mouse drag, when processing a mouse
-// click event, the application may want to retrieve the next event
-// synchronously by calling NSApplication's nextEventMatchingMask method.
-// In this case, [NSApplication sendEvent:] causes deadlock.
-// So we need to use [NSApplication postEvent:atStart:] for mouse click
-// events. In order to notify the caller correctly after all events has been
-// processed, we setup a task to watch for the event queue time to time and
-// notify the caller as soon as there is no event in the queue.
-//
-// TODO(suzhe):
-// 1. Investigate why using [NSApplication postEvent:atStart:] for keyboard
-// events causes BrowserKeyEventsTest.CommandKeyEvents to fail.
-// See http://crbug.com/49270
-// 2. On OSX 10.6, [NSEvent addLocalMonitorForEventsMatchingMask:handler:] may
-// be used, so that we don't need to poll the event queue time to time.
-
-namespace {
-
-// Stores the current mouse location on the screen. So that we can use it
-// when firing keyboard and mouse click events.
-NSPoint g_mouse_location = { 0, 0 };
-
-bool g_ui_controls_enabled = false;
-
-// From
-// http://stackoverflow.com/questions/1597383/cgeventtimestamp-to-nsdate
-// Which credits Apple sample code for this routine.
-uint64_t UpTimeInNanoseconds(void) {
- uint64_t time;
- uint64_t timeNano;
- static mach_timebase_info_data_t sTimebaseInfo;
-
- time = mach_absolute_time();
-
- // Convert to nanoseconds.
-
- // If this is the first time we've run, get the timebase.
- // We can use denom == 0 to indicate that sTimebaseInfo is
- // uninitialised because it makes no sense to have a zero
- // denominator is a fraction.
- if (sTimebaseInfo.denom == 0) {
- (void) mach_timebase_info(&sTimebaseInfo);
- }
-
- // This could overflow; for testing needs we probably don't care.
- timeNano = time * sTimebaseInfo.numer / sTimebaseInfo.denom;
- return timeNano;
-}
-
-NSTimeInterval TimeIntervalSinceSystemStartup() {
- return UpTimeInNanoseconds() / 1000000000.0;
-}
-
-// Creates and returns an autoreleased key event.
-NSEvent* SynthesizeKeyEvent(NSWindow* window,
- bool keyDown,
- ui::KeyboardCode keycode,
- NSUInteger flags) {
- unichar character;
- unichar characterIgnoringModifiers;
- int macKeycode = ui::MacKeyCodeForWindowsKeyCode(
- keycode, flags, &character, &characterIgnoringModifiers);
-
- if (macKeycode < 0)
- return nil;
-
- NSString* charactersIgnoringModifiers =
- [[[NSString alloc] initWithCharacters:&characterIgnoringModifiers
- length:1]
- autorelease];
- NSString* characters =
- [[[NSString alloc] initWithCharacters:&character length:1] autorelease];
-
- NSEventType type = (keyDown ? NSKeyDown : NSKeyUp);
-
- // Modifier keys generate NSFlagsChanged event rather than
- // NSKeyDown/NSKeyUp events.
- if (keycode == ui::VKEY_CONTROL || keycode == ui::VKEY_SHIFT ||
- keycode == ui::VKEY_MENU || keycode == ui::VKEY_COMMAND)
- type = NSFlagsChanged;
-
- // For events other than mouse moved, [event locationInWindow] is
- // UNDEFINED if the event is not NSMouseMoved. Thus, the (0,0)
- // location should be fine.
- NSEvent* event =
- [NSEvent keyEventWithType:type
- location:NSZeroPoint
- modifierFlags:flags
- timestamp:TimeIntervalSinceSystemStartup()
- windowNumber:[window windowNumber]
- context:nil
- characters:characters
- charactersIgnoringModifiers:charactersIgnoringModifiers
- isARepeat:NO
- keyCode:(unsigned short)macKeycode];
-
- return event;
-}
-
-// Creates the proper sequence of autoreleased key events for a key down + up.
-void SynthesizeKeyEventsSequence(NSWindow* window,
- ui::KeyboardCode keycode,
- bool control,
- bool shift,
- bool alt,
- bool command,
- std::vector<NSEvent*>* events) {
- NSEvent* event = nil;
- NSUInteger flags = 0;
- if (control) {
- flags |= NSControlKeyMask;
- event = SynthesizeKeyEvent(window, true, ui::VKEY_CONTROL, flags);
- DCHECK(event);
- events->push_back(event);
- }
- if (shift) {
- flags |= NSShiftKeyMask;
- event = SynthesizeKeyEvent(window, true, ui::VKEY_SHIFT, flags);
- DCHECK(event);
- events->push_back(event);
- }
- if (alt) {
- flags |= NSAlternateKeyMask;
- event = SynthesizeKeyEvent(window, true, ui::VKEY_MENU, flags);
- DCHECK(event);
- events->push_back(event);
- }
- if (command) {
- flags |= NSCommandKeyMask;
- event = SynthesizeKeyEvent(window, true, ui::VKEY_COMMAND, flags);
- DCHECK(event);
- events->push_back(event);
- }
-
- event = SynthesizeKeyEvent(window, true, keycode, flags);
- DCHECK(event);
- events->push_back(event);
- event = SynthesizeKeyEvent(window, false, keycode, flags);
- DCHECK(event);
- events->push_back(event);
-
- if (command) {
- flags &= ~NSCommandKeyMask;
- event = SynthesizeKeyEvent(window, false, ui::VKEY_COMMAND, flags);
- DCHECK(event);
- events->push_back(event);
- }
- if (alt) {
- flags &= ~NSAlternateKeyMask;
- event = SynthesizeKeyEvent(window, false, ui::VKEY_MENU, flags);
- DCHECK(event);
- events->push_back(event);
- }
- if (shift) {
- flags &= ~NSShiftKeyMask;
- event = SynthesizeKeyEvent(window, false, ui::VKEY_SHIFT, flags);
- DCHECK(event);
- events->push_back(event);
- }
- if (control) {
- flags &= ~NSControlKeyMask;
- event = SynthesizeKeyEvent(window, false, ui::VKEY_CONTROL, flags);
- DCHECK(event);
- events->push_back(event);
- }
-}
-
-// A helper function to watch for the event queue. The specific task will be
-// fired when there is no more event in the queue.
-void EventQueueWatcher(const base::Closure& task) {
- NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
- untilDate:nil
- inMode:NSDefaultRunLoopMode
- dequeue:NO];
- // If there is still event in the queue, then we need to check again.
- if (event) {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&EventQueueWatcher, task));
- } else {
- base::MessageLoop::current()->PostTask(FROM_HERE, task);
- }
-}
-
-// Returns the NSWindow located at |g_mouse_location|. NULL if there is no
-// window there, or if the window located there is not owned by the application.
-// On Mac, unless dragging, mouse events are sent to the window under the
-// cursor. Note that the OS will ignore transparent windows and windows that
-// explicitly ignore mouse events.
-NSWindow* WindowAtCurrentMouseLocation() {
- NSInteger window_number = [NSWindow windowNumberAtPoint:g_mouse_location
- belowWindowWithWindowNumber:0];
- return
- [[NSApplication sharedApplication] windowWithWindowNumber:window_number];
-}
-
-} // namespace
-
-namespace ui_controls {
-
-void EnableUIControls() {
- g_ui_controls_enabled = true;
-}
-
-bool SendKeyPress(gfx::NativeWindow window,
- ui::KeyboardCode key,
- bool control,
- bool shift,
- bool alt,
- bool command) {
- CHECK(g_ui_controls_enabled);
- return SendKeyPressNotifyWhenDone(window, key,
- control, shift, alt, command,
- base::Closure());
-}
-
-// Win and Linux implement a SendKeyPress() this as a
-// SendKeyPressAndRelease(), so we should as well (despite the name).
-bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
- ui::KeyboardCode key,
- bool control,
- bool shift,
- bool alt,
- bool command,
- const base::Closure& task) {
- CHECK(g_ui_controls_enabled);
- DCHECK(base::MessageLoopForUI::IsCurrent());
-
- std::vector<NSEvent*> events;
- SynthesizeKeyEventsSequence(
- window, key, control, shift, alt, command, &events);
-
- // TODO(suzhe): Using [NSApplication postEvent:atStart:] here causes
- // BrowserKeyEventsTest.CommandKeyEvents to fail. See http://crbug.com/49270
- // But using [NSApplication sendEvent:] should be safe for keyboard events,
- // because until now, no code wants to retrieve the next event when handling
- // a keyboard event.
- for (std::vector<NSEvent*>::iterator iter = events.begin();
- iter != events.end(); ++iter)
- [[NSApplication sharedApplication] sendEvent:*iter];
-
- if (!task.is_null()) {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&EventQueueWatcher, task));
- }
-
- return true;
-}
-
-bool SendMouseMove(long x, long y) {
- CHECK(g_ui_controls_enabled);
- return SendMouseMoveNotifyWhenDone(x, y, base::Closure());
-}
-
-// Input position is in screen coordinates. However, NSMouseMoved
-// events require them window-relative, so we adjust. We *DO* flip
-// the coordinate space, so input events can be the same for all
-// platforms. E.g. (0,0) is upper-left.
-bool SendMouseMoveNotifyWhenDone(long x, long y, const base::Closure& task) {
- CHECK(g_ui_controls_enabled);
- CGFloat screenHeight =
- [[[NSScreen screens] objectAtIndex:0] frame].size.height;
- g_mouse_location = NSMakePoint(x, screenHeight - y); // flip!
-
- NSWindow* window = WindowAtCurrentMouseLocation();
-
- NSPoint pointInWindow = g_mouse_location;
- if (window)
- pointInWindow = [window convertScreenToBase:pointInWindow];
- NSTimeInterval timestamp = TimeIntervalSinceSystemStartup();
-
- NSEvent* event =
- [NSEvent mouseEventWithType:NSMouseMoved
- location:pointInWindow
- modifierFlags:0
- timestamp:timestamp
- windowNumber:[window windowNumber]
- context:nil
- eventNumber:0
- clickCount:0
- pressure:0.0];
- [[NSApplication sharedApplication] postEvent:event atStart:NO];
-
- if (!task.is_null()) {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&EventQueueWatcher, task));
- }
-
- return true;
-}
-
-bool SendMouseEvents(MouseButton type, int state) {
- CHECK(g_ui_controls_enabled);
- return SendMouseEventsNotifyWhenDone(type, state, base::Closure());
-}
-
-bool SendMouseEventsNotifyWhenDone(MouseButton type, int state,
- const base::Closure& task) {
- CHECK(g_ui_controls_enabled);
- // On windows it appears state can be (UP|DOWN). It is unclear if
- // that'll happen here but prepare for it just in case.
- if (state == (UP|DOWN)) {
- return (SendMouseEventsNotifyWhenDone(type, DOWN, base::Closure()) &&
- SendMouseEventsNotifyWhenDone(type, UP, task));
- }
- NSEventType etype = 0;
- if (type == LEFT) {
- if (state == UP) {
- etype = NSLeftMouseUp;
- } else {
- etype = NSLeftMouseDown;
- }
- } else if (type == MIDDLE) {
- if (state == UP) {
- etype = NSOtherMouseUp;
- } else {
- etype = NSOtherMouseDown;
- }
- } else if (type == RIGHT) {
- if (state == UP) {
- etype = NSRightMouseUp;
- } else {
- etype = NSRightMouseDown;
- }
- } else {
- return false;
- }
- NSWindow* window = WindowAtCurrentMouseLocation();
- NSPoint pointInWindow = g_mouse_location;
- if (window)
- pointInWindow = [window convertScreenToBase:pointInWindow];
-
- NSEvent* event =
- [NSEvent mouseEventWithType:etype
- location:pointInWindow
- modifierFlags:0
- timestamp:TimeIntervalSinceSystemStartup()
- windowNumber:[window windowNumber]
- context:nil
- eventNumber:0
- clickCount:1
- pressure:(state == DOWN ? 1.0 : 0.0 )];
- [[NSApplication sharedApplication] postEvent:event atStart:NO];
-
- if (!task.is_null()) {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&EventQueueWatcher, task));
- }
-
- return true;
-}
-
-bool SendMouseClick(MouseButton type) {
- CHECK(g_ui_controls_enabled);
- return SendMouseEventsNotifyWhenDone(type, UP|DOWN, base::Closure());
-}
-
-void RunClosureAfterAllPendingUIEvents(const base::Closure& closure) {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&EventQueueWatcher, closure));
-}
-
-bool IsFullKeyboardAccessEnabled() {
- return [NSApp isFullKeyboardAccessEnabled];
-}
-
-} // namespace ui_controls
« no previous file with comments | « ui/base/test/ui_controls_internal_win.cc ('k') | ui/base/test/ui_controls_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698