Enabling The Orientation Sensor in Desktop Applications for Ultrabook™ on Windows* 8

Ultrabook™ devices support more than one screen orientation such as landscape, portrait, face-up, etc. Depending on the application and use case, specific orientations can be used to provide an optimal user experience. While some games, such as Angry Birds* or car racing games, might only be suitable to function in landscape mode, others such as Doodle Jump* might best be suited for Portrait mode. Application developers have the liberty to confine their applications to one specific mode or provide support for multiple orientation modes by managing UI elements appropriately.

Windows* RT has an API to support the orientation sensor, which notifies when there is a change in the device’s current orientation. It also provides more detailed information on different orientations such as face up, portrait down, face down, etc. In our Photo Application, we layout the application UI accordingly in different orientations to best utilize the available screen real-estate in different orientations. Landscape and Portrait mode UI screenshots for the Photo Application are shown below. It can be noticed from the pictures that the UI components are positioned for the best possible user experience. User Interface Design Guidelines for Great User Experience article covers more details on the User Experience aspects of the Photo Application.

Landscape Mode UI – Photo Application

NOTE: This application is developed on Windows 8 Release Preview. We noticed that the orientation notifications received from the Operating System might be opposite of what a typical user might expect. E.g. the orientation received from the OS for the screenshot above is “Portrait” as displayed in the Information Panel. In the Photo Application we work around this by rendering Landscape mode UI design when the detected orientation is Portrait and vice versa.

Portrait Mode UI – Photo Application

Implementation

Orientation sensor is one type of device sensor that allows applications to respond to changes in the device orientation. SimpleOrientationSensor class of Windows Runtime provides different events and methods to access device orientation. OrientationChanged event is raised when the device’s current orientation is changed and provides the device’s current orientation details.

The following sections illustrate how to detect the device’s current orientation and orientation change events.

Step: 1

Declare a private variable of SimpleOrientationSensor type into MainWindowViewModel class and also declare "_orientationMode" string variable to store a string representation of the current orientation value.

 //ViewModelBase is the base class for all view models. It provides INotifyPropertyChanged implementation to all its derived classes. class MainWindowViewModel : ViewModelBase { //Member variables //declare variable of SimpleOrientationSensor class private SimpleOrientationSensor orientationSensor; //String variable to store current orientation sensor value private string _orientationMode; //Declare public orientation changed event raised when current orientation changes //This is raised when SetOrientationModeProperty is called public event EventHandler<OrientatationChangedEventArgs> OrientationChanged; ..... } 

Step: 2

In the MainWindowViewModel() constructor, get the default simple orientation sensor of the device and register for "OrientationChanged" event. Then, get the current value of the sensor by calling "GetCurrentOrientation()".

 class MainWindowViewModel : ViewModelBase { public MainWindowViewModel() { //Get default SimpleOrientationSensor. orientationSensor = SimpleOrientationSensor.GetDefault(); //Register for the event to get the orientation changed notification. orientationSensor.OrientationChanged += orientationSensor_OrientationChanged ; //Get the current orientation and set the string to show the current orientation SetOrientationModeProperty(orientationSensor.GetCurrentOrientation()); ..... } ..... } 

Step: 3

When the device sensor detects an orientation change, it notifies the event handler with a new value. We have already registered for this "OrientationChanged" event in the MainWindowViewModel() constructor. Fetch the new reading from the event arguments, e.g., "SimpleOrientationSensorOrientationChangedEventArgs args" and assign the appropriate string value to "OrientationMode" property.

 class MainWindowViewModel : ViewModelBase { //Event handler notified when orientation changed void orientationSensor_OrientationChanged(SimpleOrientationSensor sender, SimpleOrientationSensorOrientationChangedEventArgs args) { SetOrientationModeProperty(args.Orientation); } ..... } 

Step: 4

SimpleOrientationSensor class provides enums (SimpleOrientation) for various orientation values. The names of these enums are not that meaningful. So, we declared the enum and wrote a method to map this enum to a value from SimpleOrientation.

 public enum ViewOrientationMode { OrientationModeUnknown = -1, OrientationModePortraitUp , OrientationModePortraitDown , OrientationModeLandScapeRight , OrientationModeLandScapeLeft , OrientationModeFaceUp , OrientationModeFaceDown }; 

Step: 5

Declare a public property to provide access to the current orientation. Implement INotifyPropertChanged interface to provide auto-notification when the new value is set to the underlying "_orientationMode" variable.

 class MainWindowViewModel : ViewModelBase { //Create public property public string OrientationMode { get { return _orientationMode; } set { if (_ orientationMode != value) { _ orientationMode = value; //Raises notification when new value is set for this variable. OnNotifyPropertyChanged("OrientationMode"); } } } ..... } 

Step: 6

Write a method to map the enum SimpleOrientation to our ViewOrientationMode enum. Also this method will send the notification to view class about orientation changes, so that the view class can change the layout accordingly.

 class MainWindowViewModel : ViewModelBase { void SetOrientationModeProperty( SimpleOrientation orientation ) { ViewOrientationMode vOrientation = ViewOrientationMode.OrientationModeUnknown; switch(orientation) { case SimpleOrientation.NotRotated: { OrientationMode = “Portrait”; vOrientation = ViewOrientationMode.OrientationModePortraitUp; break; } case SimpleOrientation.Roated90DegreesCounterclockwise: { OrientationMode = “Landscape”; vOrientation= ViewOrientationMode.OrientationModeLandScapeLeft; break; } ..... default: break; } //Send Notification to view to change the layout. If (OrientationChanged != null) OrientationChanged(this, new OrientationChangedEventArgs(vOrientation)); } ..... } 

Step: 7 Change Layout

To receive an orientation changed event, first register for that “OrientationChanged” event from the main window’s code-behind file. Call the “ChangeLayout” method into the orientation changed event handle. “ChangeLayout” has logic to re-layout all elements as per the current orientation. It resets different elements into grid’s columns and rows as required.

 class MainWindow: ViewModelBase { MainWindow() { //Register for receiving orientation changed notification vm.OrientationChanged = vm_OrientationChanged; ….. } //OrientationChanged Event Handler void vm_OrientationChanged(object sender, OrientationChangeEventArgs e) { //Do all re-layouting work in background and once ready for rendering, give it to main UI thread Dispatcher.BeginInvoke(new Action(() => ChangeLayout(e.viewOrientation)), null); } void ChangeLayout(ViewOrientationMode currentOrientationMode) { //Portrait mode if (currentOrientationMode == ViewOrientationMode.OrientationModeFaceUp || currentOrientationMode == ViewOrientationMode.OrientationModeFaceDown || currentOrientationMode == ViewOrientationMode.OrientationModePortraitUp || currentOrientationMode == ViewOrientationMode.OrientationModePortraitDown) { //Change the layouts for controls. Grid.SetRow(debugPanel, 0); Grid.SetColumn(debugPanel, 1); debugGraphicaPanel.Orientation = Orientation.Vertical; Grid.SetRow(listBoxGrid, 0); Grid.SetColumn(listBoxGrid, 0); Grid.SetColumnSpan(listBoxGrid, 1); Grid.SetRow(controlsGrid, 0); Grid.SetColumn(controlsGrid, 1); Grid.SetColumn(controlsBtnPanel, 0); Grid.SetColumn(cameraBtn, 1); imagesListBox.Height = lbActualHeight; //Reset the orientation for camera button & controls panel. controlsGrid.HorizontalAlignment = HorizontalAlignment.Right; cameraBtn.HorizontalAlignment = HorizontalAlignment.Right; //Change the scrollbar visibility. if (imageScrollViewer != null) imageScrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden; } else if (currentOrienationMode == ViewOrientationMode.OrientationModeLandScapeLeft || currentOrientationMode == ViewOrientationMode.OrientationModeLandScapeRight) //LandScape mode { //Change the layouts for controls. Grid.SetRow(debugPanel, 1); Grid.SetColumn(debugPanel, 0); debugGraphicaPanel.Orientation = Orientation.Horizontal; Grid.SetRow(listBoxGrid, 1); Grid.SetColumn(listBoxGrid, 0); Grid.SetColumnSpan(listBoxGrid, 2); Grid.SetRow(controlsGrid, 0); Grid.SetColumn(controlsGrid, 0); //Set the image list box to show only 2 rows. imagesListBox.Height = 275; //Set the orientation for camera button & controls panel accordingly. if (currentOrientationMode == ViewOrientationMode.OrientationModeLandScapeRight) { controlsGrid.HorizontalAlignment = HorizontalAlignment.Right; Grid.SetColumn(controlsBtnPanel, 0); Grid.SetColumn(cameraBtn, 1); } else { controlsGrid.HorizontalAlignment = HorizontalAlignment.Left; Grid.SetColumn(controlsBtnPanel, 1); Grid.SetColumn(cameraBtn, 0); } //Change the scrollbar visibility to hide the multiple rows in list. if (imageScrollViewer != null) imageScrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled; } } ….. } 

Photo Application UI and Orientations:

Convertible Ultrabook devices have two working modes (I) Tablet Mode and (ii) Laptop Mode. When the device’s display and keypad are in the same plane, we consider it to be “tablet” mode. When the keypad and display are perpendicular to each other, we consider it to be “laptop” mode.

Laptop Face-up mode

Laptop face-up mode is when the device’s display and keyboard are perpendicular to each other. The following screenshot shows how the Photo Application looks in this mode.

Tablet portrait mode

When the device’s display and keyboard are in same plane and the display is above the keypad, we consider this to be the tablet portrait mode. The following screenshot shows how the photo app looks in this mode.

Laptop landscape mode

When the device’s display and keyboard are perpendicular to each other and the device is in vertical orientation, we consider this to be the laptop landscape mode. The following screenshot shows how the photo app looks in this mode.

Tablet landscape mode

When the device’s display and keyboard are in the same plane and either the display is left or right of the attached keypad, we consider this to be the tablet landscape mode. The following screenshot shows how the photo app looks in this mode.

Additional Resources

Ultrabook and Tablet Windows* 8 Sensors Development Guide

UltrabookTM Desktop Applications Development on Windows* 8: Photo Application with Touch and Sensors

Notices

INFORMATION IN THIS DOCUMENT IS PROVIDED IN CONNECTION WITH INTEL PRODUCTS. NO LICENSE, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, TO ANY INTELLECTUAL PROPERTY RIGHTS IS GRANTED BY THIS DOCUMENT. EXCEPT AS PROVIDED IN INTEL'S TERMS AND CONDITIONS OF SALE FOR SUCH PRODUCTS, INTEL ASSUMES NO LIABILITY WHATSOEVER AND INTEL DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY, RELATING TO SALE AND/OR USE OF INTEL PRODUCTS INCLUDING LIABILITY OR WARRANTIES RELATING TO FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR INFRINGEMENT OF ANY PATENT, COPYRIGHT OR OTHER INTELLECTUAL PROPERTY RIGHT.

UNLESS OTHERWISE AGREED IN WRITING BY INTEL, THE INTEL PRODUCTS ARE NOT DESIGNED NOR INTENDED FOR ANY APPLICATION IN WHICH THE FAILURE OF THE INTEL PRODUCT COULD CREATE A SITUATION WHERE PERSONAL INJURY OR DEATH MAY OCCUR.

Intel may make changes to specifications and product descriptions at any time, without notice. Designers must not rely on the absence or characteristics of any features or instructions marked "reserved" or "undefined." Intel reserves these for future definition and shall have no responsibility whatsoever for conflicts or incompatibilities arising from future changes to them. The information here is subject to change without notice. Do not finalize a design with this information.

The products described in this document may contain design defects or errors known as errata which may cause the product to deviate from published specifications. Current characterized errata are available on request.

Contact your local Intel sales office or your distributor to obtain the latest specifications and before placing your product order.

Copies of documents which have an order number and are referenced in this document, or other Intel literature, may be obtained by calling 1-800-548-4725, or go to: http://www.intel.com/design/literature.htm

Software and workloads used in performance tests may have been optimized for performance only on Intel microprocessors. Performance tests, such as SYSmark and MobileMark, are measured using specific computer systems, components, software, operations, and functions. Any change to any of those factors may cause the results to vary. You should consult other information and performance tests to assist you in fully evaluating your contemplated purchases, including the performance of that product when combined with other products.

Any software source code reprinted in this document is furnished under a software license and may only be used or copied in accordance with the terms of that license.

Intel, Ultrabook, and the Intel logo are trademarks of Intel Corporation in the US and/or other countries.

Copyright © 2012 Intel Corporation. All rights reserved.

*Other names and brands may be claimed as the property of others.

AttachmentSize
Download o1.png1.23 MB
Download o2.png857.91 KB
Download o3.png1.49 MB
Download o4.png1.52 MB
Download o5.png1.15 MB
Download o6.png1.15 MB
For more complete information about compiler optimizations, see our Optimization Notice.

Comments