@@ -109,16 +109,89 @@ public DeviceType DeviceType
109
109
}
110
110
}
111
111
112
- static readonly int SM_CONVERTIBLESLATEMODE = 0x2003 ;
113
- static readonly int SM_TABLETPC = 0x56 ;
112
+ /// <summary>
113
+ /// Whether or not the device is in "tablet mode" or not. This
114
+ /// has to be implemented by the device manufacturer.
115
+ /// </summary>
116
+ const int SM_CONVERTIBLESLATEMODE = 0x2003 ;
117
+
118
+ /// <summary>
119
+ /// How many fingers (aka touches) are supported for touch control
120
+ /// </summary>
121
+ const int SM_MAXIMUMTOUCHES = 95 ;
122
+
123
+ /// <summary>
124
+ /// Whether a physical keyboard is attached or not.
125
+ /// Manufacturers have to remember to set this.
126
+ /// Defaults to not-attached.
127
+ /// </summary>
128
+ const int SM_ISDOCKED = 0x2004 ;
129
+
114
130
115
131
[ DllImport ( "user32.dll" , SetLastError = true , CharSet = CharSet . Auto ) ]
116
132
static extern int GetSystemMetrics ( int nIndex ) ;
117
133
134
+ [ DllImport ( "user32.dll" , SetLastError = true , CharSet = CharSet . Auto ) ]
135
+ static extern bool GetAutoRotationState ( ref AutoRotationState pState ) ;
136
+
137
+ [ DllImport ( "Powrprof.dll" , SetLastError = true , CharSet = CharSet . Auto ) ]
138
+ static extern PowerPlatformRole PowerDeterminePlatformRoleEx ( ulong Version ) ;
139
+
118
140
static bool GetIsInTabletMode ( )
119
141
{
120
- var supportsTablet = GetSystemMetrics ( SM_TABLETPC ) != 0 ;
121
- var inTabletMode = GetSystemMetrics ( SM_CONVERTIBLESLATEMODE ) == 0 ;
122
- return inTabletMode && supportsTablet ;
142
+ // Adopt Chromium's methodology for determining tablet mode
143
+ // https://source.chromium.org/chromium/chromium/src/+/main:base/win/win_util.cc;l=537;drc=ac83a5a2d3c04763d86ce16d92f3904cc9566d3a;bpv=0;bpt=1
144
+ // Device does not have a touchscreen
145
+ if ( GetSystemMetrics ( SM_MAXIMUMTOUCHES ) == 0 )
146
+ {
147
+ return false ;
148
+ }
149
+
150
+ // If the device is docked, user is treating as a PC
151
+ if ( GetSystemMetrics ( SM_ISDOCKED ) != 0 )
152
+ {
153
+ return false ;
154
+ }
155
+
156
+ // Fetch device rotation. Possible for this to fail.
157
+ AutoRotationState rotationState = AutoRotationState . AR_ENABLED ;
158
+ bool success = GetAutoRotationState ( ref rotationState ) ;
159
+
160
+ // Fetch succeeded and device does not support rotation
161
+ if ( success && ( rotationState & ( AutoRotationState . AR_NOT_SUPPORTED | AutoRotationState . AR_LAPTOP | AutoRotationState . AR_NOSENSOR ) ) != 0 )
162
+ {
163
+ return false ;
164
+ }
165
+
166
+ // Check if power management says we are mobile (laptop) or a tablet
167
+ if ( ( PowerDeterminePlatformRoleEx ( 2 ) & ( PowerPlatformRole . PlatformRoleMobile | PowerPlatformRole . PlatformRoleSlate ) ) != 0 )
168
+ {
169
+ // Check if tablet mode is 0. 0 is default value.
170
+ return GetSystemMetrics ( SM_CONVERTIBLESLATEMODE ) == 0 ;
171
+ }
172
+
173
+ return false ;
123
174
}
124
175
}
176
+
177
+ /// <summary>
178
+ /// Represents the OEM's preferred power management profile,
179
+ /// Useful in-case OEM implements one but not the other
180
+ /// </summary>
181
+ enum PowerPlatformRole
182
+ {
183
+ PlatformRoleMobile = 2 ,
184
+ PlatformRoleSlate = 8 ,
185
+ }
186
+
187
+ /// <summary>
188
+ /// Whether rotation is supported or not.
189
+ /// Rotation is only supported if AR_ENABLED is true
190
+ /// </summary>
191
+ enum AutoRotationState
192
+ {
193
+ AR_ENABLED = 0x0 ,
194
+ AR_NOT_SUPPORTED = 0x20 ,
195
+ AR_LAPTOP = 0x80 ,
196
+ AR_NOSENSOR = 0x10 ,
197
+ }
0 commit comments