summaryrefslogtreecommitdiffstats
path: root/native_client_sdk
diff options
context:
space:
mode:
authornoelallen@chromium.org <noelallen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-19 18:05:32 +0000
committernoelallen@chromium.org <noelallen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-19 18:05:32 +0000
commite1968efcfb120afd19ddb250e51f42489d465acd (patch)
tree96182c216cae5c5cc17bd83163ec211e6ec8002e /native_client_sdk
parent55ec8b532bf7ee58b9ecf0fc45c029def3419d1d (diff)
downloadchromium_src-e1968efcfb120afd19ddb250e51f42489d465acd.zip
chromium_src-e1968efcfb120afd19ddb250e51f42489d465acd.tar.gz
chromium_src-e1968efcfb120afd19ddb250e51f42489d465acd.tar.bz2
Fix Mouselock
There appears to be a race in mouselock in which we can get calls to DidChangeView due to a Fullscreen switch request, however we are not yet in fullscreen. Combined with a request to switch to mouselock this can get into a state were we fail to correctly track the mouselock state. The fact that fullscreen has a IsFullscreen, yet mouselock does not also complicates matters. This CL removes as much of the logic as possible, and simply recreates the draw context every time DidChangeView is called. In addition it seperates the request to change view with the request to get mouse lock. The combination cleans up the logic and removes the need for the assert which was causing the crash. R=binji@chromium.org BUG=114091 NOTRY=true Review URL: https://chromiumcodereview.appspot.com/11620003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@173945 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'native_client_sdk')
-rw-r--r--native_client_sdk/src/examples/mouselock/index.html39
-rw-r--r--native_client_sdk/src/examples/mouselock/mouselock.cc119
-rw-r--r--native_client_sdk/src/examples/mouselock/mouselock.h5
3 files changed, 95 insertions, 68 deletions
diff --git a/native_client_sdk/src/examples/mouselock/index.html b/native_client_sdk/src/examples/mouselock/index.html
index 63214e2..e28c8c5 100644
--- a/native_client_sdk/src/examples/mouselock/index.html
+++ b/native_client_sdk/src/examples/mouselock/index.html
@@ -21,39 +21,36 @@ found in the LICENSE file.
"browser fullscreen".
<ul>
<li>Tab fullscreen refers to when a tab enters fullscreen mode via the
- JS or Pepper fullscreen API.</li>
+ JS or Pepper fullscreen API. The NaCl Module will enter or
+ exit fullscreen when it has focus and the enter key is pressed.</li>
<li>Browser fullscreen refers to the user putting the browser itself
into fullscreen mode from the UI (e.g., pressing F11).</li>
</ul>
- <span style="font-weight:bold">
- NOTE: Mouse lock is only allowed in "tab fullscreen" mode.
- </span>
</li>
<li>Lock mouse:
<ul>
- <li>left click in the grey box; or</li>
- <li>right click in the box to ensure that it is focused and
- then press Enter key. (You could verify that the tooltip window is
- dismissed properly by this second approach.)</li>
+ <li>Mouse Lock refers to removing the standard mouse cursor, and
+ sending mouse messages to the module even when the cursor is outside
+ of the module's bounding box. The NaCl module will enter or exit
+ mouse lock by clicking on the grey box representing the bounding
+ area of the module.
</ul>
</li>
- <li>Unlock mouse voluntarily (i.e., NaCl module unlocks mouse):
+ <li>Involuntary fullscreen or mouselock loss.
<ul>
- <li>press Enter.</li>
- </ul>
- </li>
- <li>Unlock mouse involuntarily (i.e. Chrome unlocks mouse):
- <ul>
- <li>lose focus; or</li>
- <li>press Esc key; or</li>
- <li>exit from the "tab fullscreen" mode.</li>
+ <li>Pressing the Esc key will cause the browser to revoke mouselock
+ or tab fullscreen priviledge.</li>
+ <li>When in browser fullscreen, pressing F11 will also revoke mouselock
+ or tab fullscreen priviledge.</li>
</ul>
</li>
</ul>
- <p>Clicking the mouse inside the grey square takes the NaCl module to/from
- combined fullscreen and mouselock mode.</p>
- <p>While in fullscreen, pressing Enter will exit/enter mouse lock mode.</p>
-
+ <p> Move the mouse cursor over the grey box to watch the captured mouse
+ movement. Notice that messages are normally not captured when the cursor
+ is outside of the grey box.</p>
+ <p> By clicking on the grey box, we set focus and turn on mouse lock. Now all
+ mouse messages are sent to the module.</p>
+ <p> This behavoir is maintianed even in tab and/or browser fullscreen.</p>
<!-- The NaCl plugin will be embedded inside the element with id "listener".
See common.js.-->
<div id="listener"></div>
diff --git a/native_client_sdk/src/examples/mouselock/mouselock.cc b/native_client_sdk/src/examples/mouselock/mouselock.cc
index 871ee67..9aefac1 100644
--- a/native_client_sdk/src/examples/mouselock/mouselock.cc
+++ b/native_client_sdk/src/examples/mouselock/mouselock.cc
@@ -32,8 +32,7 @@ namespace {
const int kCentralSpotRadius = 5;
const uint32_t kReturnKeyCode = 13;
const uint32_t kBackgroundColor = 0xff606060;
-const uint32_t kLockedForegroundColor = 0xfff08080;
-const uint32_t kUnlockedForegroundColor = 0xff80f080;
+const uint32_t kForegroundColor = 0xfff08080;
} // namespace
namespace mouselock {
@@ -54,25 +53,11 @@ bool MouseLockInstance::Init(uint32_t argc,
bool MouseLockInstance::HandleInputEvent(const pp::InputEvent& event) {
switch (event.GetType()) {
case PP_INPUTEVENT_TYPE_MOUSEDOWN: {
- is_context_bound_ = false;
- if (fullscreen_.IsFullscreen()) {
- // Leaving fullscreen mode also unlocks the mouse if it was locked.
- // In this case, the browser will call MouseLockLost() on this
- // instance.
- if (!fullscreen_.SetFullscreen(false)) {
- Log("Could not leave fullscreen mode\n");
- }
+ if (mouse_locked_) {
+ UnlockMouse();
} else {
- if (!fullscreen_.SetFullscreen(true)) {
- Log("Could not set fullscreen mode\n");
- } else {
- pp::MouseInputEvent mouse_event(event);
- if (mouse_event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_LEFT &&
- !mouse_locked_) {
- LockMouse(callback_factory_.NewCallback(
- &MouseLockInstance::DidLockMouse));
- }
- }
+ LockMouse(callback_factory_.NewCallback(
+ &MouseLockInstance::DidLockMouse));
}
return true;
}
@@ -86,13 +71,25 @@ bool MouseLockInstance::HandleInputEvent(const pp::InputEvent& event) {
case PP_INPUTEVENT_TYPE_KEYDOWN: {
pp::KeyboardInputEvent key_event(event);
- // Lock the mouse when the Enter key is pressed.
+
+ // Switch in and out of fullscreen when 'Enter' is hit
if (key_event.GetKeyCode() == kReturnKeyCode) {
- if (mouse_locked_) {
- UnlockMouse();
+ // Ignore switch if in transition
+ if (!is_context_bound_)
+ return true;
+
+ if (fullscreen_.IsFullscreen()) {
+ if (!fullscreen_.SetFullscreen(false)) {
+ Log("Could not leave fullscreen mode\n");
+ } else {
+ is_context_bound_ = false;
+ }
} else {
- LockMouse(callback_factory_.NewCallback(
- &MouseLockInstance::DidLockMouse));
+ if (!fullscreen_.SetFullscreen(true)) {
+ Log("Could not enter fullscreen mode\n");
+ } else {
+ is_context_bound_ = false;
+ }
}
}
return true;
@@ -121,88 +118,118 @@ bool MouseLockInstance::HandleInputEvent(const pp::InputEvent& event) {
}
void MouseLockInstance::DidChangeView(const pp::View& view) {
- // When entering into full-screen mode, DidChangeView() gets called twice.
- // The first time, any 2D context will fail to bind to this pp::Instacne.
- if (view.GetRect().size() == size_ && is_context_bound_) {
+ // DidChangeView can get called for many reasons, so we only want to
+ // rebuild the device context if we really need to.
+
+ if ((size_ == view.GetRect().size()) &&
+ (was_fullscreen_ == view.IsFullscreen()) && is_context_bound_) {
+ Log("DidChangeView SKIP %d,%d FULL=%s CTX Bound=%s",
+ view.GetRect().width(), view.GetRect().height(),
+ view.IsFullscreen() ? "true" : "false",
+ is_context_bound_ ? "true" : "false");
return;
}
- size_ = view.GetRect().size();
+ Log("DidChangeView DO %d,%d FULL=%s CTX Bound=%s",
+ view.GetRect().width(), view.GetRect().height(),
+ view.IsFullscreen() ? "true" : "false",
+ is_context_bound_ ? "true" : "false");
+
+ size_ = view.GetRect().size();
device_context_ = pp::Graphics2D(this, size_, false);
waiting_for_flush_completion_ = false;
- free(background_scanline_);
- background_scanline_ = NULL;
+
is_context_bound_ = BindGraphics(device_context_);
if (!is_context_bound_) {
- Log("Could not bind to 2D context\n");
+ Log("Could not bind to 2D context\n.");
return;
+ } else {
+ Log("Bound to 2D context size %d,%d.\n", size_.width(), size_.height());
}
- background_scanline_ = static_cast<uint32_t*>(
- malloc(size_.width() * sizeof(*background_scanline_)));
+
+ // Create a scanline for fill.
+ delete[] background_scanline_;
+ background_scanline_ = new uint32_t[size_.width()];
uint32_t* bg_pixel = background_scanline_;
for (int x = 0; x < size_.width(); ++x) {
*bg_pixel++ = kBackgroundColor;
}
+
+ // Remember if we are fullscreen or not
+ was_fullscreen_ = view.IsFullscreen();
+
+ // Paint this context
Paint();
}
void MouseLockInstance::MouseLockLost() {
if (mouse_locked_) {
+ Log("Mouselock unlocked.\n");
mouse_locked_ = false;
Paint();
- } else {
- PP_NOTREACHED();
}
}
void MouseLockInstance::DidLockMouse(int32_t result) {
mouse_locked_ = result == PP_OK;
+ if (result != PP_OK) {
+ Log("Mouselock failed with failed with error number %d.\n", result);
+ }
mouse_movement_.set_x(0);
mouse_movement_.set_y(0);
Paint();
}
void MouseLockInstance::DidFlush(int32_t result) {
+ if (result != 0) Log("Flushed failed with error number %d.\n", result);
waiting_for_flush_completion_ = false;
}
void MouseLockInstance::Paint() {
+ // If we are already waiting to paint...
if (waiting_for_flush_completion_) {
return;
}
+
pp::ImageData image = PaintImage(size_);
if (image.is_null()) {
Log("Could not create image data\n");
return;
}
+
device_context_.ReplaceContents(&image);
waiting_for_flush_completion_ = true;
device_context_.Flush(
callback_factory_.NewCallback(&MouseLockInstance::DidFlush));
}
+
pp::ImageData MouseLockInstance::PaintImage(const pp::Size& size) {
pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, false);
- if (image.is_null() || image.data() == NULL)
+ if (image.is_null() || image.data() == NULL) {
+ Log("Skipping image.\n");
return image;
+ }
ClearToBackground(&image);
- uint32_t foreground_color = mouse_locked_ ? kLockedForegroundColor :
- kUnlockedForegroundColor;
- DrawCenterSpot(&image, foreground_color);
- DrawNeedle(&image, foreground_color);
+
+ DrawCenterSpot(&image, kForegroundColor);
+ DrawNeedle(&image, kForegroundColor);
return image;
}
void MouseLockInstance::ClearToBackground(pp::ImageData* image) {
if (image == NULL) {
- Log("ClearToBackground with NULL image");
+ Log("ClearToBackground with NULL image.");
return;
}
- if (background_scanline_ == NULL)
+ if (background_scanline_ == NULL) {
+ Log("ClearToBackground with no scanline.");
return;
+ }
int image_height = image->size().height();
int image_width = image->size().width();
+
for (int y = 0; y < image_height; ++y) {
uint32_t* scanline = image->GetAddr32(pp::Point(0, y));
memcpy(scanline,
@@ -306,6 +333,10 @@ void MouseLockInstance::DrawNeedle(pp::ImageData* image,
void MouseLockInstance::Log(const char* format, ...) {
+ static PPB_Console* console = (PPB_Console*)
+ pp::Module::Get()->GetBrowserInterface(PPB_CONSOLE_INTERFACE);
+
+ if (NULL == console) return;
va_list args;
va_start(args, format);
char buf[512];
@@ -314,7 +345,7 @@ void MouseLockInstance::Log(const char* format, ...) {
va_end(args);
pp::Var value(buf);
- PostMessage(value);
+ console->Log(pp_instance(), PP_LOGLEVEL_ERROR, value.pp_var());
}
} // namespace mouselock
diff --git a/native_client_sdk/src/examples/mouselock/mouselock.h b/native_client_sdk/src/examples/mouselock/mouselock.h
index 62f48f2..56be1d7 100644
--- a/native_client_sdk/src/examples/mouselock/mouselock.h
+++ b/native_client_sdk/src/examples/mouselock/mouselock.h
@@ -36,6 +36,7 @@ class MouseLockInstance : public pp::Instance, public pp::MouseLock {
callback_factory_(this),
fullscreen_(this),
is_context_bound_(false),
+ was_fullscreen_(false),
background_scanline_(NULL) {
}
virtual ~MouseLockInstance();
@@ -80,11 +81,8 @@ class MouseLockInstance : public pp::Instance, public pp::MouseLock {
// Fill the image with the backgroud color.
void ClearToBackground(pp::ImageData* image);
- // Draw a spot in |spot_color| in the center of the image. The radius of the
- // spot is defined by a constant value in mouselock.cc
void DrawCenterSpot(pp::ImageData* image, uint32_t spot_color);
- // Draw the needle when the mouse is outside of the central spot.
void DrawNeedle(pp::ImageData* image, uint32_t needle_color);
// Print the printf-style format to the "console" via PostMessage.
@@ -100,6 +98,7 @@ class MouseLockInstance : public pp::Instance, public pp::MouseLock {
pp::Fullscreen fullscreen_;
pp::Graphics2D device_context_;
bool is_context_bound_;
+ bool was_fullscreen_;
uint32_t* background_scanline_;
};