31 #include "com_sun_glass_ui_Screen.h" 32 33 extern BOOL CALLBACK CountMonitorsCallback(HMONITOR hMon, HDC hDC, LPRECT rRect, LPARAM lP); 34 extern BOOL CALLBACK CollectMonitorsCallback(HMONITOR hMonitor, HDC hDC, LPRECT rRect, LPARAM lP); 35 36 enum AnchorType { 37 ANCHOR_TO_LEFT, 38 ANCHOR_TO_TOP, 39 ANCHOR_TO_RIGHT, 40 ANCHOR_TO_BOTTOM 41 }; 42 43 struct MonitorInfoStruct { 44 HMONITOR hMonitor; 45 RECT rcMonitor; 46 RECT rcWork; 47 RECT fxMonitor; 48 RECT fxWork; 49 jboolean primaryScreen; 50 jint colorDepth; 51 jfloat uiScale; 52 jfloat renderScale; 53 jint dpiX; 54 jint dpiY; 55 jint anchoredInPass; 56 jobject gScreen; 57 }; 58 extern jobject CreateJavaMonitorFromMIS(JNIEnv *env, MonitorInfoStruct *pMIS); 59 60 struct { 61 int numInfos; 62 int maxInfos; 63 MonitorInfoStruct *pMonitorInfos; 64 } g_MonitorInfos; 65 66 typedef enum _Monitor_DPI_Type { 67 MDT_Effective_DPI = 0, 68 MDT_Angular_DPI = 1, 69 MDT_Raw_DPI = 2, 70 MDT_Default = MDT_Effective_DPI 71 } Monitor_DPI_Type; 72 173 174 ::GetMonitorInfo(hMonitor, &mix); 175 176 ::CopyRect(&mis->rcMonitor, &mix.rcMonitor); 177 ::CopyRect(&mis->rcWork, &mix.rcWork); 178 #ifdef DEBUG_DPI 179 fprintf(stderr, "raw monitor bounds = (%d, %d, %d, %d)\n", 180 mis->rcMonitor.left, mis->rcMonitor.top, 181 mis->rcMonitor.right, mis->rcMonitor.bottom); 182 fprintf(stderr, "raw monitor working bounds = (%d, %d, %d, %d)\n", 183 mis->rcWork.left, mis->rcWork.top, 184 mis->rcWork.right, mis->rcWork.bottom); 185 #endif /* DEBUG_DPI */ 186 187 HDC hDC = ::CreateDC(TEXT("DISPLAY"), mix.szDevice, NULL, NULL); 188 ASSERT(hDC); 189 190 mis->primaryScreen = ((mix.dwFlags & MONITORINFOF_PRIMARY) != 0) ? JNI_TRUE : JNI_FALSE; 191 mis->colorDepth = ::GetDeviceCaps(hDC, BITSPIXEL) * ::GetDeviceCaps(hDC, PLANES); 192 UINT resx, resy; 193 UINT uires; 194 if (pGetDPIForMonitor) { 195 // If we can use the GetDPIForMonitor function, then its Effective 196 // value will tell us how much we should scale ourselves based on 197 // all system settings, and its Raw value will tell us exactly how 198 // many pixels per inch there are. The Effective value can be 199 // affected by user preference, accessibility settings, monitor 200 // size, and resolution all computed by the system into a single 201 // value that all applications should scale themselves by. 202 #ifdef DEBUG_DPI 203 fprintf(stderr, "logpixelsX,Y = %d, %d\n", 204 ::GetDeviceCaps(hDC, LOGPIXELSX), 205 ::GetDeviceCaps(hDC, LOGPIXELSY)); 206 #endif /* DEBUG_DPI */ 207 HRESULT res = (*pGetDPIForMonitor)(hMonitor, MDT_Effective_DPI, &resx, &resy); 208 #ifdef DEBUG_DPI 209 fprintf(stderr, "effective DPI X,Y = [0x%08x] %d, %d\n", res, resx, resy); 210 #endif /* DEBUG_DPI */ 211 if (res != S_OK) { 212 resx = ::GetDeviceCaps(hDC, LOGPIXELSX); 213 resy = ::GetDeviceCaps(hDC, LOGPIXELSY); 214 } 215 uires = resx; 216 res = (*pGetDPIForMonitor)(hMonitor, MDT_Raw_DPI, &resx, &resy); 217 #ifdef DEBUG_DPI 218 fprintf(stderr, "raw DPI X,Y = [0x%08x] %d, %d\n", res, resx, resy); 219 #endif /* DEBUG_DPI */ 220 } else { 221 resx = ::GetDeviceCaps(hDC, LOGPIXELSX); 222 resy = ::GetDeviceCaps(hDC, LOGPIXELSY); 223 #ifdef DEBUG_DPI 224 fprintf(stderr, "logpixelsX,Y = %d, %d\n", resx, resy); 225 #endif /* DEBUG_DPI */ 226 uires = resx; 227 } 228 mis->dpiX = resx; 229 mis->dpiY = resy; 230 mis->uiScale = GlassApplication::GetUIScale(uires); 231 mis->renderScale = GlassApplication::getRenderScale(mis->uiScale); 232 233 ::DeleteDC(hDC); 234 } 235 236 jclass GetScreenCls(JNIEnv *env) 237 { 238 static jclass screenCls = NULL; 239 if (!screenCls) { 240 jclass cls = GlassApplication::ClassForName(env, "com.sun.glass.ui.Screen"); 241 ASSERT(cls); 242 screenCls = (jclass)env->NewGlobalRef(cls); 243 env->DeleteLocalRef(cls); 244 } 245 return screenCls; 246 } 247 248 void anchor(MonitorInfoStruct *pMIS, int pass); 249 250 jobject GlassScreen::GetJavaMonitor(JNIEnv *env, HMONITOR monitor) 251 { 262 263 MonitorInfoStruct mis; 264 memset(&mis, 0, sizeof(MonitorInfoStruct)); 265 GetMonitorSettings(monitor, &mis); 266 anchor(&mis, 0); 267 268 jobject gScreen = CreateJavaMonitorFromMIS(env, &mis); 269 // The return value (gScreen) is a local ref in addition to the global 270 // ref stored in the mis.gScreen field. We should not leave the global 271 // ref laying around in this case because we are not saving the "mis" 272 // structure. 273 env->DeleteGlobalRef(mis.gScreen); 274 return gScreen; 275 } 276 277 jobject CreateJavaMonitorFromMIS(JNIEnv *env, MonitorInfoStruct *pMIS) 278 { 279 jclass screenCls = GetScreenCls(env); 280 281 if (javaIDs.Screen.init == NULL) { 282 javaIDs.Screen.init = env->GetMethodID(screenCls, "<init>", "(JIIIIIIIIIIIFF)V"); 283 ASSERT(javaIDs.Screen.init); 284 if (CheckAndClearException(env)) return NULL; 285 } 286 287 jobject gScn = env->NewObject(screenCls, javaIDs.Screen.init, 288 ptr_to_jlong(pMIS->hMonitor), 289 290 pMIS->colorDepth, 291 pMIS->fxMonitor.left, 292 pMIS->fxMonitor.top, 293 pMIS->fxMonitor.right - pMIS->fxMonitor.left, 294 pMIS->fxMonitor.bottom - pMIS->fxMonitor.top, 295 296 pMIS->fxWork.left, 297 pMIS->fxWork.top, 298 pMIS->fxWork.right - pMIS->fxWork.left, 299 pMIS->fxWork.bottom - pMIS->fxWork.top, 300 301 pMIS->dpiX, 302 pMIS->dpiY, 303 304 pMIS->uiScale, 305 pMIS->renderScale); 306 if (CheckAndClearException(env)) return NULL; 307 pMIS->gScreen = env->NewGlobalRef(gScn); 308 return gScn; 309 } 310 311 void GlassScreen::HandleDisplayChange() 312 { 313 JNIEnv *env = GetEnv(); 314 315 jclass screenCls = GetScreenCls(env); 316 317 if (javaIDs.Screen.notifySettingsChanged == NULL) { 318 javaIDs.Screen.notifySettingsChanged 319 = env->GetStaticMethodID(screenCls, "notifySettingsChanged", "()V"); 320 ASSERT(javaIDs.Screen.notifySettingsChanged); 321 if (CheckAndClearException(env)) return; 322 } 323 324 env->CallStaticVoidMethod(screenCls, javaIDs.Screen.notifySettingsChanged); 325 CheckAndClearException(env); 373 } 374 convert(g_MonitorInfos.pMonitorInfos[monIndex].rcMonitor, 375 g_MonitorInfos.pMonitorInfos[monIndex].fxMonitor, 376 pX, pY); 377 return TRUE; 378 } 379 380 void anchorTo(MonitorInfoStruct *pMIS, 381 jint fxX, jboolean xBefore, 382 jint fxY, jboolean yBefore, 383 jint pass) 384 { 385 jint monX = pMIS->rcMonitor.left; 386 jint monY = pMIS->rcMonitor.top; 387 jint monW = pMIS->rcMonitor.right - monX; 388 jint monH = pMIS->rcMonitor.bottom - monY; 389 jint wrkL = pMIS->rcWork .left - monX; 390 jint wrkT = pMIS->rcWork .top - monY; 391 jint wrkR = pMIS->rcWork .right - monX; 392 jint wrkB = pMIS->rcWork .bottom - monY; 393 jfloat scale = pMIS->uiScale; 394 if (scale > 1.0f) { 395 pMIS->dpiX = (jint) floorf((pMIS->dpiX / scale) + 0.5f); 396 pMIS->dpiY = (jint) floorf((pMIS->dpiY / scale) + 0.5f); 397 monW = (jint) floorf((monW / scale) + 0.5f); 398 monH = (jint) floorf((monH / scale) + 0.5f); 399 wrkL = (jint) floorf((wrkL / scale) + 0.5f); 400 wrkT = (jint) floorf((wrkT / scale) + 0.5f); 401 wrkR = (jint) floorf((wrkR / scale) + 0.5f); 402 wrkB = (jint) floorf((wrkB / scale) + 0.5f); 403 } 404 405 if (xBefore) fxX -= monW; 406 if (yBefore) fxY -= monH; 407 pMIS->fxMonitor.left = fxX; 408 pMIS->fxMonitor.top = fxY; 409 pMIS->fxMonitor.right = fxX + monW; 410 pMIS->fxMonitor.bottom = fxY + monH; 411 pMIS->fxWork .left = fxX + wrkL; 412 pMIS->fxWork .top = fxY + wrkT; 413 pMIS->fxWork .right = fxX + wrkR; 414 pMIS->fxWork .bottom = fxY + wrkB; 415 pMIS->anchoredInPass = pass; 416 } 417 418 void anchor(MonitorInfoStruct *pMIS, int pass) { 419 anchorTo(pMIS, 420 pMIS->rcMonitor.left, JNI_FALSE, 421 pMIS->rcMonitor.top, JNI_FALSE, 422 pass); 423 } 424 425 jint originOffsetFromRanges(jint aV0, jint aV1, 426 jint mV0, jint mV1, 427 jfloat aScale, jfloat mScale) 428 { 429 jint v0 = (aV0 > mV0) ? aV0 : mV0; 430 jint v1 = (aV1 < mV1) ? aV1 : mV1; 431 jfloat mid = (v0 + v1) / 2.0f; 432 jfloat rel = (mid - aV0) / aScale - (mid - mV0) / mScale; 433 return (jint) floorf(rel + 0.5f); 434 } 435 436 void anchorH(MonitorInfoStruct *pAnchor, MonitorInfoStruct *pMon, 437 jboolean before, jint pass) 438 { 439 int x = before ? pAnchor->fxMonitor.left : pAnchor->fxMonitor.right; 440 int yoff = originOffsetFromRanges(pAnchor->rcMonitor.top, pAnchor->rcMonitor.bottom, 441 pMon->rcMonitor.top, pMon->rcMonitor.bottom, 442 pAnchor->uiScale, pMon->uiScale); 443 int y = pAnchor->fxMonitor.top + yoff; 444 anchorTo(pMon, x, before, y, false, pass); 445 } 446 447 void anchorV(MonitorInfoStruct *pAnchor, MonitorInfoStruct *pMon, 448 jboolean before, jint pass) 449 { 450 int xoff = originOffsetFromRanges(pAnchor->rcMonitor.left, pAnchor->rcMonitor.right, 451 pMon->rcMonitor.left, pMon->rcMonitor.right, 452 pAnchor->uiScale, pMon->uiScale); 453 int x = pAnchor->fxMonitor.left + xoff; 454 int y = before ? pAnchor->fxMonitor.top : pAnchor->fxMonitor.bottom; 455 anchorTo(pMon, x, false, y, before, pass); 456 } 457 458 BOOL touchesLeft(MonitorInfoStruct *pMISa, MonitorInfoStruct *pMISb) { 459 return (pMISa->rcMonitor.left == pMISb->rcMonitor.right && 460 pMISa->rcMonitor.top < pMISb->rcMonitor.bottom && 461 pMISa->rcMonitor.bottom > pMISb->rcMonitor.top); 462 } 463 464 BOOL touchesAbove(MonitorInfoStruct *pMISa, MonitorInfoStruct *pMISb) { 465 return (pMISa->rcMonitor.top == pMISb->rcMonitor.bottom && 466 pMISa->rcMonitor.left < pMISb->rcMonitor.right && 467 pMISa->rcMonitor.right > pMISb->rcMonitor.left); 468 } 469 470 void propagateAnchors(MonitorInfoStruct *pMIS, jint pass) { 471 for (int i = 0; i < g_MonitorInfos.numInfos; i++) { 472 MonitorInfoStruct *pMIS2 = &g_MonitorInfos.pMonitorInfos[i]; | 31 #include "com_sun_glass_ui_Screen.h" 32 33 extern BOOL CALLBACK CountMonitorsCallback(HMONITOR hMon, HDC hDC, LPRECT rRect, LPARAM lP); 34 extern BOOL CALLBACK CollectMonitorsCallback(HMONITOR hMonitor, HDC hDC, LPRECT rRect, LPARAM lP); 35 36 enum AnchorType { 37 ANCHOR_TO_LEFT, 38 ANCHOR_TO_TOP, 39 ANCHOR_TO_RIGHT, 40 ANCHOR_TO_BOTTOM 41 }; 42 43 struct MonitorInfoStruct { 44 HMONITOR hMonitor; 45 RECT rcMonitor; 46 RECT rcWork; 47 RECT fxMonitor; 48 RECT fxWork; 49 jboolean primaryScreen; 50 jint colorDepth; 51 jfloat uiScaleX; 52 jfloat uiScaleY; 53 jint dpiX; 54 jint dpiY; 55 jint anchoredInPass; 56 jobject gScreen; 57 }; 58 extern jobject CreateJavaMonitorFromMIS(JNIEnv *env, MonitorInfoStruct *pMIS); 59 60 struct { 61 int numInfos; 62 int maxInfos; 63 MonitorInfoStruct *pMonitorInfos; 64 } g_MonitorInfos; 65 66 typedef enum _Monitor_DPI_Type { 67 MDT_Effective_DPI = 0, 68 MDT_Angular_DPI = 1, 69 MDT_Raw_DPI = 2, 70 MDT_Default = MDT_Effective_DPI 71 } Monitor_DPI_Type; 72 173 174 ::GetMonitorInfo(hMonitor, &mix); 175 176 ::CopyRect(&mis->rcMonitor, &mix.rcMonitor); 177 ::CopyRect(&mis->rcWork, &mix.rcWork); 178 #ifdef DEBUG_DPI 179 fprintf(stderr, "raw monitor bounds = (%d, %d, %d, %d)\n", 180 mis->rcMonitor.left, mis->rcMonitor.top, 181 mis->rcMonitor.right, mis->rcMonitor.bottom); 182 fprintf(stderr, "raw monitor working bounds = (%d, %d, %d, %d)\n", 183 mis->rcWork.left, mis->rcWork.top, 184 mis->rcWork.right, mis->rcWork.bottom); 185 #endif /* DEBUG_DPI */ 186 187 HDC hDC = ::CreateDC(TEXT("DISPLAY"), mix.szDevice, NULL, NULL); 188 ASSERT(hDC); 189 190 mis->primaryScreen = ((mix.dwFlags & MONITORINFOF_PRIMARY) != 0) ? JNI_TRUE : JNI_FALSE; 191 mis->colorDepth = ::GetDeviceCaps(hDC, BITSPIXEL) * ::GetDeviceCaps(hDC, PLANES); 192 UINT resx, resy; 193 UINT uiresx, uiresy; 194 if (pGetDPIForMonitor) { 195 // If we can use the GetDPIForMonitor function, then its Effective 196 // value will tell us how much we should scale ourselves based on 197 // all system settings, and its Raw value will tell us exactly how 198 // many pixels per inch there are. The Effective value can be 199 // affected by user preference, accessibility settings, monitor 200 // size, and resolution all computed by the system into a single 201 // value that all applications should scale themselves by. 202 #ifdef DEBUG_DPI 203 fprintf(stderr, "logpixelsX,Y = %d, %d\n", 204 ::GetDeviceCaps(hDC, LOGPIXELSX), 205 ::GetDeviceCaps(hDC, LOGPIXELSY)); 206 #endif /* DEBUG_DPI */ 207 HRESULT res = (*pGetDPIForMonitor)(hMonitor, MDT_Effective_DPI, &resx, &resy); 208 #ifdef DEBUG_DPI 209 fprintf(stderr, "effective DPI X,Y = [0x%08x] %d, %d\n", res, resx, resy); 210 #endif /* DEBUG_DPI */ 211 if (res != S_OK) { 212 resx = ::GetDeviceCaps(hDC, LOGPIXELSX); 213 resy = ::GetDeviceCaps(hDC, LOGPIXELSY); 214 } 215 uiresx = resx; 216 uiresy = resy; 217 res = (*pGetDPIForMonitor)(hMonitor, MDT_Raw_DPI, &resx, &resy); 218 #ifdef DEBUG_DPI 219 fprintf(stderr, "raw DPI X,Y = [0x%08x] %d, %d\n", res, resx, resy); 220 #endif /* DEBUG_DPI */ 221 } else { 222 resx = ::GetDeviceCaps(hDC, LOGPIXELSX); 223 resy = ::GetDeviceCaps(hDC, LOGPIXELSY); 224 #ifdef DEBUG_DPI 225 fprintf(stderr, "logpixelsX,Y = %d, %d\n", resx, resy); 226 #endif /* DEBUG_DPI */ 227 uiresx = resx; 228 uiresy = resy; 229 } 230 mis->dpiX = resx; 231 mis->dpiY = resy; 232 mis->uiScaleX = GlassApplication::GetUIScale(uiresx); 233 mis->uiScaleY = GlassApplication::GetUIScale(uiresy); 234 235 ::DeleteDC(hDC); 236 } 237 238 jclass GetScreenCls(JNIEnv *env) 239 { 240 static jclass screenCls = NULL; 241 if (!screenCls) { 242 jclass cls = GlassApplication::ClassForName(env, "com.sun.glass.ui.Screen"); 243 ASSERT(cls); 244 screenCls = (jclass)env->NewGlobalRef(cls); 245 env->DeleteLocalRef(cls); 246 } 247 return screenCls; 248 } 249 250 void anchor(MonitorInfoStruct *pMIS, int pass); 251 252 jobject GlassScreen::GetJavaMonitor(JNIEnv *env, HMONITOR monitor) 253 { 264 265 MonitorInfoStruct mis; 266 memset(&mis, 0, sizeof(MonitorInfoStruct)); 267 GetMonitorSettings(monitor, &mis); 268 anchor(&mis, 0); 269 270 jobject gScreen = CreateJavaMonitorFromMIS(env, &mis); 271 // The return value (gScreen) is a local ref in addition to the global 272 // ref stored in the mis.gScreen field. We should not leave the global 273 // ref laying around in this case because we are not saving the "mis" 274 // structure. 275 env->DeleteGlobalRef(mis.gScreen); 276 return gScreen; 277 } 278 279 jobject CreateJavaMonitorFromMIS(JNIEnv *env, MonitorInfoStruct *pMIS) 280 { 281 jclass screenCls = GetScreenCls(env); 282 283 if (javaIDs.Screen.init == NULL) { 284 javaIDs.Screen.init = env->GetMethodID(screenCls, "<init>", "(JIIIIIIIIIIIIIIIFFFF)V"); 285 ASSERT(javaIDs.Screen.init); 286 if (CheckAndClearException(env)) return NULL; 287 } 288 289 jobject gScn = env->NewObject(screenCls, javaIDs.Screen.init, 290 ptr_to_jlong(pMIS->hMonitor), 291 292 pMIS->colorDepth, 293 pMIS->fxMonitor.left, 294 pMIS->fxMonitor.top, 295 pMIS->fxMonitor.right - pMIS->fxMonitor.left, 296 pMIS->fxMonitor.bottom - pMIS->fxMonitor.top, 297 298 pMIS->rcMonitor.left, 299 pMIS->rcMonitor.top, 300 pMIS->rcMonitor.right - pMIS->rcMonitor.left, 301 pMIS->rcMonitor.bottom - pMIS->rcMonitor.top, 302 303 pMIS->fxWork.left, 304 pMIS->fxWork.top, 305 pMIS->fxWork.right - pMIS->fxWork.left, 306 pMIS->fxWork.bottom - pMIS->fxWork.top, 307 308 pMIS->dpiX, 309 pMIS->dpiY, 310 311 pMIS->uiScaleX, 312 pMIS->uiScaleY, 313 pMIS->uiScaleX, 314 pMIS->uiScaleY); 315 if (CheckAndClearException(env)) return NULL; 316 pMIS->gScreen = env->NewGlobalRef(gScn); 317 return gScn; 318 } 319 320 void GlassScreen::HandleDisplayChange() 321 { 322 JNIEnv *env = GetEnv(); 323 324 jclass screenCls = GetScreenCls(env); 325 326 if (javaIDs.Screen.notifySettingsChanged == NULL) { 327 javaIDs.Screen.notifySettingsChanged 328 = env->GetStaticMethodID(screenCls, "notifySettingsChanged", "()V"); 329 ASSERT(javaIDs.Screen.notifySettingsChanged); 330 if (CheckAndClearException(env)) return; 331 } 332 333 env->CallStaticVoidMethod(screenCls, javaIDs.Screen.notifySettingsChanged); 334 CheckAndClearException(env); 382 } 383 convert(g_MonitorInfos.pMonitorInfos[monIndex].rcMonitor, 384 g_MonitorInfos.pMonitorInfos[monIndex].fxMonitor, 385 pX, pY); 386 return TRUE; 387 } 388 389 void anchorTo(MonitorInfoStruct *pMIS, 390 jint fxX, jboolean xBefore, 391 jint fxY, jboolean yBefore, 392 jint pass) 393 { 394 jint monX = pMIS->rcMonitor.left; 395 jint monY = pMIS->rcMonitor.top; 396 jint monW = pMIS->rcMonitor.right - monX; 397 jint monH = pMIS->rcMonitor.bottom - monY; 398 jint wrkL = pMIS->rcWork .left - monX; 399 jint wrkT = pMIS->rcWork .top - monY; 400 jint wrkR = pMIS->rcWork .right - monX; 401 jint wrkB = pMIS->rcWork .bottom - monY; 402 jfloat scalex = pMIS->uiScaleX; 403 jfloat scaley = pMIS->uiScaleY; 404 if (scalex != 1.0f) { 405 pMIS->dpiX = (jint) floorf((pMIS->dpiX / scalex) + 0.5f); 406 monW = (jint) floorf((monW / scalex) + 0.5f); 407 wrkL = (jint) floorf((wrkL / scalex) + 0.5f); 408 wrkR = (jint) floorf((wrkR / scalex) + 0.5f); 409 } 410 if (scaley != 1.0f) { 411 pMIS->dpiY = (jint) floorf((pMIS->dpiY / scaley) + 0.5f); 412 monH = (jint) floorf((monH / scaley) + 0.5f); 413 wrkT = (jint) floorf((wrkT / scaley) + 0.5f); 414 wrkB = (jint) floorf((wrkB / scaley) + 0.5f); 415 } 416 417 if (xBefore) fxX -= monW; 418 if (yBefore) fxY -= monH; 419 pMIS->fxMonitor.left = fxX; 420 pMIS->fxMonitor.top = fxY; 421 pMIS->fxMonitor.right = fxX + monW; 422 pMIS->fxMonitor.bottom = fxY + monH; 423 pMIS->fxWork .left = fxX + wrkL; 424 pMIS->fxWork .top = fxY + wrkT; 425 pMIS->fxWork .right = fxX + wrkR; 426 pMIS->fxWork .bottom = fxY + wrkB; 427 pMIS->anchoredInPass = pass; 428 } 429 430 void anchor(MonitorInfoStruct *pMIS, int pass) { 431 anchorTo(pMIS, 432 pMIS->rcMonitor.left, JNI_FALSE, 433 pMIS->rcMonitor.top, JNI_FALSE, 434 pass); 435 } 436 437 jint originOffsetFromRanges(jint aV0, jint aV1, 438 jint mV0, jint mV1, 439 jfloat aScale, jfloat mScale) 440 { 441 jint v0 = (aV0 > mV0) ? aV0 : mV0; 442 jint v1 = (aV1 < mV1) ? aV1 : mV1; 443 jfloat mid = (v0 + v1) / 2.0f; 444 jfloat rel = (mid - aV0) / aScale - (mid - mV0) / mScale; 445 return (jint) floorf(rel + 0.5f); 446 } 447 448 void anchorH(MonitorInfoStruct *pAnchor, MonitorInfoStruct *pMon, 449 jboolean before, jint pass) 450 { 451 int x = before ? pAnchor->fxMonitor.left : pAnchor->fxMonitor.right; 452 int yoff = originOffsetFromRanges(pAnchor->rcMonitor.top, pAnchor->rcMonitor.bottom, 453 pMon->rcMonitor.top, pMon->rcMonitor.bottom, 454 pAnchor->uiScaleY, pMon->uiScaleY); 455 int y = pAnchor->fxMonitor.top + yoff; 456 anchorTo(pMon, x, before, y, false, pass); 457 } 458 459 void anchorV(MonitorInfoStruct *pAnchor, MonitorInfoStruct *pMon, 460 jboolean before, jint pass) 461 { 462 int xoff = originOffsetFromRanges(pAnchor->rcMonitor.left, pAnchor->rcMonitor.right, 463 pMon->rcMonitor.left, pMon->rcMonitor.right, 464 pAnchor->uiScaleX, pMon->uiScaleX); 465 int x = pAnchor->fxMonitor.left + xoff; 466 int y = before ? pAnchor->fxMonitor.top : pAnchor->fxMonitor.bottom; 467 anchorTo(pMon, x, false, y, before, pass); 468 } 469 470 BOOL touchesLeft(MonitorInfoStruct *pMISa, MonitorInfoStruct *pMISb) { 471 return (pMISa->rcMonitor.left == pMISb->rcMonitor.right && 472 pMISa->rcMonitor.top < pMISb->rcMonitor.bottom && 473 pMISa->rcMonitor.bottom > pMISb->rcMonitor.top); 474 } 475 476 BOOL touchesAbove(MonitorInfoStruct *pMISa, MonitorInfoStruct *pMISb) { 477 return (pMISa->rcMonitor.top == pMISb->rcMonitor.bottom && 478 pMISa->rcMonitor.left < pMISb->rcMonitor.right && 479 pMISa->rcMonitor.right > pMISb->rcMonitor.left); 480 } 481 482 void propagateAnchors(MonitorInfoStruct *pMIS, jint pass) { 483 for (int i = 0; i < g_MonitorInfos.numInfos; i++) { 484 MonitorInfoStruct *pMIS2 = &g_MonitorInfos.pMonitorInfos[i]; |