modules/graphics/src/main/native-glass/win/GlassScreen.cpp

Print this page




  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];