void MCStack::realize() { if (MCnoui) { start_externals(); return; } if (MCModeMakeLocalWindows()) { uint32_t wstyle, exstyle; loadwindowshape(); getstyle(wstyle, exstyle); RECT wrect ; // IM-2013-09-23: [[ FullscreenMode ]] Don't change stack rect if fullscreen /* CODE DELETED */ wrect = getwrect(rect, wstyle, exstyle); LONG x = wrect.left; LONG y = wrect.top; LONG width = wrect.right - wrect.left; LONG height = wrect.bottom - wrect.top; if (flags & F_WM_PLACE && !(state & CS_BEEN_MOVED)) x = CW_USEDEFAULT; window = new _Drawable; window->type = DC_WINDOW; window->handle.window = 0; // protect against creation callbacks // MW-2011-02-15: [[ Bug 9396 ]] Tooltips should have a shadow on Windows. Boolean isxpmenu = (mode == WM_PULLDOWN || mode == WM_POPUP || mode == WM_CASCADE || mode == WM_TOOLTIP) \ && (MCcurtheme && MCcurtheme->getthemeid() == LF_NATIVEWIN); // MW-2012-09-07: [[ Bug 10368 ]] If the 'no-shadow' bit is set, then we don't // want to use the menu class. if (getflag(F_DECORATIONS) && (decorations & WD_NOSHADOW) != 0) isxpmenu = False; HWND t_parenthwnd = NULL; // MW-2007-07-06: [[ Bug 3226 ]] If the platform is NT always create a Unicode window if ((MCruntimebehaviour & RTB_NO_UNICODE_WINDOWS) == 0 && !isxpmenu && mode < WM_PULLDOWN) window -> handle . window = (MCSysWindowHandle)CreateWindowExW(exstyle, MC_WIN_CLASS_NAME_W, WideCString(getname_cstring()),wstyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, x, y, width, height, t_parenthwnd, NULL, MChInst, NULL); else window->handle.window = (MCSysWindowHandle)CreateWindowExA(exstyle, isxpmenu? MC_MENU_WIN_CLASS_NAME: mode >= WM_PULLDOWN ? MC_POPUP_WIN_CLASS_NAME : MC_WIN_CLASS_NAME, getname_cstring(), wstyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, x, y, width, height, t_parenthwnd, NULL, MChInst, NULL); SetWindowLongA((HWND)window->handle.window, GWL_USERDATA, mode); if (flags & F_DECORATIONS && !(decorations & WD_SHAPE) && !(decorations & WD_CLOSE)) EnableMenuItem(GetSystemMenu((HWND)window->handle.window, False), SC_CLOSE, MF_BYCOMMAND | MF_GRAYED); if (m_window_shape != nil && m_window_shape -> is_sharp) { MCRegionRef t_region; t_region = (MCRegionRef)m_window_shape -> handle; MCRegionOffset(t_region, rect . x - wrect . left, rect . y - wrect . top); MCRegionSetAsWindowShape(t_region, window->handle.window); // The window now owns the region. m_window_shape -> handle = nil; } if ((m_window_shape == NULL || m_window_shape -> is_sharp) && blendlevel != 100) setopacity(blendlevel * 255 / 100); } start_externals(); }
void MCStack::effectrect(const MCRectangle& p_area, Boolean& r_abort) { // Get the list of effects. MCEffectList *t_effects = MCcur_effects; MCcur_effects = NULL; // If the window isn't opened or hasn't been attached (plugin) or if we have no // snapshot to use, this is a no-op. if (!opened || !haswindow() || m_snapshot == nil) { while(t_effects != NULL) { MCEffectList *t_effect; t_effect = t_effects; t_effects = t_effects -> next; delete t_effect; } return; } // Mark the stack as being in an effect. state |= CS_EFFECT; // Lock messages while the effect is happening. Boolean t_old_lockmessages; t_old_lockmessages = MClockmessages; MClockmessages = True; // Calculate the area of interest. MCRectangle t_effect_area; t_effect_area = curcard -> getrect(); t_effect_area . y = getscroll(); t_effect_area . height -= t_effect_area . y; t_effect_area = MCU_intersect_rect(t_effect_area, p_area); // IM-2013-08-21: [[ ResIndependence ]] Scale effect area to device coords // Align snapshot rect to device pixels // IM-2013-09-30: [[ FullscreenMode ]] Use stack transform to get device coords MCGAffineTransform t_transform; t_transform = getdevicetransform(); // MW-2013-10-29: [[ Bug 11330 ]] Make sure the effect area is cropped to the visible // area. t_effect_area = MCRectangleGetTransformedBounds(t_effect_area, getviewtransform()); t_effect_area = MCU_intersect_rect(t_effect_area, MCU_make_rect(0, 0, view_getrect() . width, view_getrect() . height)); // IM-2014-01-24: [[ HiDPI ]] scale effect region to backing surface coords MCGFloat t_scale; t_scale = view_getbackingscale(); MCRectangle t_device_rect, t_user_rect; t_device_rect = MCRectangleGetScaledBounds(t_effect_area, t_scale); t_user_rect = MCRectangleGetTransformedBounds(t_device_rect, MCGAffineTransformInvert(t_transform)); // IM-2013-08-29: [[ RefactorGraphics ]] get device height for CoreImage effects // IM-2013-09-30: [[ FullscreenMode ]] Use view rect to get device height uint32_t t_device_height; t_device_height = floor(view_getrect().height * t_scale); // Make a region of the effect area // IM-2013-08-29: [[ ResIndependence ]] scale effect region to device coords MCRegionRef t_effect_region; t_effect_region = nil; /* UNCHECKED */ MCRegionCreate(t_effect_region); /* UNCHECKED */ MCRegionSetRect(t_effect_region, t_effect_area); #ifndef FEATURE_PLATFORM_PLAYER #if defined(FEATURE_QUICKTIME) // MW-2010-07-07: Make sure QT is only loaded if we actually are doing an effect if (t_effects != nil) if (!MCdontuseQTeffects) if (!MCtemplateplayer -> isQTinitted()) MCtemplateplayer -> initqt(); #endif #endif // Lock the screen to prevent any updates occuring until we want them. MCRedrawLockScreen(); // By default, we have not aborted. r_abort = False; MCGImageRef t_initial_image; t_initial_image = MCGImageRetain(m_snapshot); while(t_effects != nil) { uint32_t t_duration; t_duration = MCU_max(1, MCeffectrate / (t_effects -> speed - VE_VERY)); if (t_effects -> type == VE_DISSOLVE) t_duration *= 2; uint32_t t_delta; t_delta = 0; // Create surface at effect_area size. // Render into surface based on t_effects -> image MCGImageRef t_final_image = nil; // If this isn't a plain effect, then we must fetch first and last images. if (t_effects -> type != VE_PLAIN) { // Render the final image. MCGContextRef t_context = nil; // IM-2014-05-20: [[ GraphicsPerformance ]] Create opaque context for snapshot /* UNCHECKED */ MCGContextCreate(t_device_rect.width, t_device_rect.height, false, t_context); MCGContextTranslateCTM(t_context, -t_device_rect.x, -t_device_rect.y); // IM-2013-10-03: [[ FullscreenMode ]] Apply device transform to context MCGContextConcatCTM(t_context, t_transform); // Configure the context. MCGContextClipToRect(t_context, MCRectangleToMCGRectangle(t_user_rect)); // Render an appropriate image switch(t_effects -> image) { case VE_INVERSE: { MCContext *t_old_context = nil; /* UNCHECKED */ t_old_context = new MCGraphicsContext(t_context); curcard->draw(t_old_context, t_user_rect, false); delete t_old_context; MCGContextSetFillRGBAColor(t_context, 1.0, 1.0, 1.0, 1.0); MCGContextSetBlendMode(t_context, kMCGBlendModeDifference); MCGContextAddRectangle(t_context, MCRectangleToMCGRectangle(t_user_rect)); MCGContextFill(t_context); } break; case VE_BLACK: MCGContextSetFillRGBAColor(t_context, 0.0, 0.0, 0.0, 1.0); MCGContextAddRectangle(t_context, MCRectangleToMCGRectangle(t_user_rect)); MCGContextFill(t_context); break; case VE_WHITE: MCGContextSetFillRGBAColor(t_context, 1.0, 1.0, 1.0, 1.0); MCGContextAddRectangle(t_context, MCRectangleToMCGRectangle(t_user_rect)); MCGContextFill(t_context); break; case VE_GRAY: MCGContextSetFillRGBAColor(t_context, 0.5, 0.5, 0.5, 1.0); MCGContextAddRectangle(t_context, MCRectangleToMCGRectangle(t_user_rect)); MCGContextFill(t_context); break; default: { MCContext *t_old_context = nil; /* UNCHECKED */ t_old_context = new MCGraphicsContext(t_context); curcard->draw(t_old_context, t_user_rect, false); delete t_old_context; } } /* UNCHECKED */ MCGContextCopyImage(t_context, t_final_image); MCGContextRelease(t_context); } MCStackEffectContext t_context; t_context.delta = t_delta; t_context.duration = t_duration; t_context.effect = t_effects; t_context.effect_area = t_device_rect; t_context.initial_image = t_initial_image; t_context.final_image = t_final_image; // MW-2011-10-20: [[ Bug 9824 ]] Make sure dst point is correct. // Initialize the destination with the start image. view_platform_updatewindowwithcallback(t_effect_region, MCStackRenderInitial, &t_context); // If there is a sound, then start playing it. if (t_effects -> sound != NULL) { MCAudioClip *acptr; MCNewAutoNameRef t_sound; /* UNCHECKED */ MCNameCreate(t_effects->sound, &t_sound); if ((acptr = (MCAudioClip *)getobjname(CT_AUDIO_CLIP, *t_sound)) == NULL) { IO_handle stream; if ((stream = MCS_open(t_effects->sound, kMCOpenFileModeRead, True, False, 0)) != NULL) { acptr = new MCAudioClip; acptr->setdisposable(); if (!acptr->import(t_effects->sound, stream)) { delete acptr; acptr = NULL; } MCS_close(stream); } } if (acptr != NULL) { MCU_play_stop(); MCacptr = acptr; MCU_play(); #ifndef FEATURE_PLATFORM_AUDIO if (MCacptr != NULL) MCscreen->addtimer(MCacptr, MCM_internal, PLAY_RATE); #endif } if (MCscreen->wait((real8)MCsyncrate / 1000.0, False, True)) { r_abort = True; break; } } // Initialize CoreImage of QTEffects if needed. if (t_effects -> type != VE_PLAIN) { MCAutoPointer<char> t_name; /* UNCHECKED */ MCStringConvertToCString(t_effects -> name, &t_name); #ifdef _MAC_DESKTOP // IM-2013-08-29: [[ ResIndependence ]] use scaled effect rect for CI effects if (t_effects -> type == VE_UNDEFINED && MCCoreImageEffectBegin(*t_name, t_initial_image, t_final_image, t_device_rect, t_device_height, t_effects -> arguments)) t_effects -> type = VE_CIEFFECT; else #endif #ifdef FEATURE_QUICKTIME_EFFECTS // IM-2013-08-29: [[ ResIndependence ]] use scaled effect rect for QT effects if (t_effects -> type == VE_UNDEFINED && MCQTEffectBegin(t_effects -> type, *t_name, t_effects -> direction, t_initial_image, t_final_image, t_device_rect)) t_effects -> type = VE_QTEFFECT; #else ; #endif } // Run effect // Now perform the effect loop, but only if there is something to do. if (t_effects -> type != VE_PLAIN || old_blendlevel != blendlevel) { // Calculate timing parameters. double t_start_time; t_start_time = 0.0; for(;;) { t_context.delta = t_delta; Boolean t_drawn = False; view_platform_updatewindowwithcallback(t_effect_region, MCStackRenderEffect, &t_context); // Now redraw the window with the new image. // if (t_drawn) { MCscreen -> sync(getw()); } // Update the window's blendlevel (if needed) if (old_blendlevel != blendlevel) { float t_fraction = float(t_delta) / t_duration; setopacity(uint1((old_blendlevel * 255 + (float(blendlevel) - old_blendlevel) * 255 * t_fraction) / 100)); } // If the start time is zero, then start counting from here. if (t_start_time == 0.0) t_start_time = MCS_time(); // If we've reached the end of the transition, we are done. if (t_delta == t_duration) { #ifdef _ANDROID_MOBILE // MW-2011-12-12: [[ Bug 9907 ]] Make sure we let the screen sync at this point MCscreen -> wait(0.01, False, False); #endif break; } // Get the time now. double t_now; t_now = MCS_time(); // Compute the new delta value. uint32_t t_new_delta; t_new_delta = (uint32_t)ceil((t_now - t_start_time) * 1000.0); // If the new value is same as the old, then advance one step. if (t_new_delta == t_delta) t_delta = t_new_delta + 1; else t_delta = t_new_delta; // If the new delta is beyond the end point, set it to the end. if (t_delta > t_duration) t_delta = t_duration; // Wait until the next boundary, making sure we break for no reason // other than abort. if (MCscreen -> wait((t_start_time + (t_delta / 1000.0)) - t_now, False, False)) r_abort = True; // If we aborted, we render the final step and are thus done. if (r_abort) t_delta = t_duration; } } #ifdef _MAC_DESKTOP if (t_effects -> type == VE_CIEFFECT) MCCoreImageEffectEnd(); else #endif #ifdef FEATURE_QUICKTIME_EFFECTS if (t_effects -> type == VE_QTEFFECT) MCQTEffectEnd(); #endif // Free initial surface. MCGImageRelease(t_initial_image); // initial surface becomes final surface. t_initial_image = t_final_image; t_final_image = nil; // Move to the next effect. MCEffectList *t_current_effect; t_current_effect = t_effects; t_effects = t_effects -> next; delete t_current_effect; } // Make sure the pixmaps are freed and any dangling effects // are cleaned up. if (t_effects != NULL) { /* OVERHAUL - REVISIT: error cleanup needs revised */ MCGImageRelease(t_initial_image); // MCGSurfaceRelease(t_final_image); while(t_effects != NULL) { MCEffectList *t_current_effect; t_current_effect = t_effects; t_effects = t_effects -> next; delete t_current_effect; } } MCRegionDestroy(t_effect_region); MCGImageRelease(m_snapshot); m_snapshot = nil; m_snapshot = t_initial_image; // Unlock the screen. MCRedrawUnlockScreen(); // Unlock messages. MClockmessages = t_old_lockmessages; // Turn off effect mode. state &= ~CS_EFFECT; // The stack's blendlevel is now the new one. old_blendlevel = blendlevel; // Finally, mark the affected area of the stack for a redraw. dirtyrect(p_area); }
void MCStack::realize() { //create window if (!MCnoui && MCModeMakeLocalWindows()) { if ( getextendedstate(ECS_FULLSCREEN) ) { //TS-2008-08-01 : [[Bug 5703 - fullscreen stack prop interacts badly with HideMenuBar]] if (!((MCScreenDC*)MCscreen)->getmenubarhidden()) SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar); const MCDisplay *t_display; t_display = MCscreen -> getnearestdisplay(rect); MCRectangle t_workarea, t_viewport; t_workarea = t_display -> workarea; t_viewport = t_display -> viewport ; setrect(t_viewport); } else { if (!((MCScreenDC*)MCscreen)->getmenubarhidden()) SetSystemUIMode(kUIModeNormal, NULL); } Rect wrect; MCScreenDC *psdc = (MCScreenDC *)MCscreen; psdc->MCRect2MacRect(rect, wrect); window = new _Drawable; window->type = DC_WINDOW; window->handle.window = 0; char *tmpname = NULL; const unsigned char *namePascal; if (!isunnamed()) { //set window title to name of stack temporarily. tmpname = strclone(getname_cstring()); //it will be changed by setname() later. namePascal = c2pstr(tmpname); } else namePascal = (unsigned char*)"\p"; loadwindowshape(); window->handle.window = NULL; uint32_t wclass; uint32_t wattributes; getWinstyle(wattributes,wclass); wattributes |= kWindowCompositingAttribute; long testdecorations = WD_TITLE | WD_MENU | WD_CLOSE | WD_MINIMIZE | WD_MAXIMIZE; if (m_window_shape != NULL) { static WindowDefUPP s_window_mask_proc = NULL; if (s_window_mask_proc == NULL) s_window_mask_proc = NewWindowDefUPP(WindowMaskProc); WindowDefSpec t_spec; t_spec . defType = kWindowDefProcPtr; t_spec . u . defProc = s_window_mask_proc; CreateCustomWindow(&t_spec, wclass, wattributes, &wrect, (WindowPtr *)&window -> handle . window); HIWindowChangeFeatures((WindowPtr)window -> handle . window, 0, kWindowIsOpaque); } else if (((flags & F_DECORATIONS && !(decorations & testdecorations)) || wclass == kPlainWindowClass)) { static WindowDefUPP s_borderless_proc = NULL; if (s_borderless_proc == NULL) s_borderless_proc = NewWindowDefUPP(BorderlessWindowProc); WindowDefSpec t_spec; t_spec . defType = kWindowDefProcPtr; t_spec . u . defProc = s_borderless_proc; if (wclass == kPlainWindowClass) wclass = kUtilityWindowClass; CreateCustomWindow(&t_spec, wclass, wattributes, &wrect, (WindowPtr *)&window->handle.window); } else CreateNewWindow(wclass, wattributes,&wrect, (WindowPtr *)&window->handle.window); if (wclass == kFloatingWindowClass) ChangeWindowAttributes((WindowPtr)window -> handle . window, kWindowNoAttributes, kWindowHideOnSuspendAttribute); // MW-2009-10-31: Make sure we can collapse any rev window HIWindowChangeFeatures((WindowPtr)window -> handle . window, kWindowCanCollapse, 0); if (window->handle.window == NULL) SetWTitle((WindowPtr)window->handle.window, namePascal); SetWTitle((WindowPtr)window->handle.window, namePascal); setopacity(blendlevel * 255 / 100); SetWRefCon((WindowPtr)window->handle.window, mode); ControlRef t_control; MCRevolutionStackViewCreate(this, &t_control); ControlRef t_root_control; GetRootControl((WindowPtr)window -> handle . window, &t_root_control); HIViewAddSubview(t_root_control, t_control); ShowControl(t_control); if (wclass == kDrawerWindowClass) { Window pwindow = NULL; if (parentwindow != DNULL) pwindow = parentwindow; else if (MCdefaultstackptr && MCdefaultstackptr->getw() != DNULL ) pwindow = MCdefaultstackptr->getw(); if (pwindow && GetWRefCon((WindowPtr)pwindow->handle.window) != WM_DRAWER) { SetDrawerParent((WindowPtr)window->handle.window, (WindowPtr)pwindow->handle.window); WindowAttributes watt; GetWindowAttributes((WindowPtr)pwindow->handle.window,&watt); if (wattributes & kWindowResizableAttribute) ChangeWindowAttributes((WindowPtr)pwindow->handle.window, kWindowLiveResizeAttribute, 0); OptionBits draweredge; switch (wposition) { case WP_PARENTTOP: draweredge = kWindowEdgeTop; break; case WP_PARENTRIGHT: draweredge = kWindowEdgeRight; break; case WP_PARENTBOTTOM: draweredge = kWindowEdgeBottom; break; case WP_PARENTLEFT: draweredge = kWindowEdgeLeft; break; default: draweredge = kWindowEdgeDefault; break; } SetDrawerPreferredEdge((WindowPtr)window->handle.window, draweredge); if (walignment) { MCRectangle parentwindowrect; MCscreen->getwindowgeometry(pwindow, parentwindowrect); int2 wspace = 0; RgnHandle r = NewRgn(); GetWindowRegion((WindowPtr)window->handle.window, kWindowStructureRgn, r); Rect tRect; GetRegionBounds(r, &tRect); DisposeRgn(r); MCRectangle drawerwindowrect; psdc->MacRect2MCRect(tRect, drawerwindowrect); if (wposition == WP_PARENTTOP || wposition == WP_PARENTBOTTOM) { wspace = parentwindowrect.width - drawerwindowrect.width; if (watt & kWindowMetalAttribute) if (wspace) wspace += 10; //for metal } else { wspace = parentwindowrect.height - drawerwindowrect.height; if (watt & kWindowMetalAttribute) if (wspace) wspace += 5; //for metal } if (wspace > 0) switch (walignment) { case OP_CENTER: SetDrawerOffsets ((WindowPtr)window->handle.window,ceil(wspace/2) -1,floor(wspace/2) + 1); break; case OP_RIGHT: case OP_BOTTOM: SetDrawerOffsets ((WindowPtr)window->handle.window,wspace,0); break; case OP_TOP: case OP_LEFT: SetDrawerOffsets ((WindowPtr)window->handle.window,0,wspace); break; } } } } delete tmpname; // MW-2005-11-06: We also need to catch window constraining events so we can flush // the screen geometry cache. EventTypeSpec list[] = { {kEventClassWindow, kEventWindowCollapsed}, {kEventClassWindow, kEventWindowExpanded}, {kEventClassMouse, kEventMouseWheelMoved}, {kEventClassWindow, kEventWindowBoundsChanging}, {kEventClassWindow, kEventWindowBoundsChanged}, {kEventClassWindow, kEventWindowConstrain}, {kEventClassWindow, kEventWindowFocusAcquired}, {kEventClassWindow, kEventWindowFocusRelinquish}, {kEventClassWindow, kEventWindowActivated}, {kEventClassWindow, kEventWindowDeactivated}, {kEventClassWindow, kEventWindowClose}, }; EventHandlerRef ref; // MW-2005-09-07: Pass the window handle as user data, otherwise 'takewindow' causes problems InstallWindowEventHandler((WindowPtr)window->handle.window, MCS_weh, sizeof(list) / sizeof(EventTypeSpec), list, (WindowPtr)window -> handle . window, &ref); ChangeWindowAttributes((WindowPtr)window->handle.window, 0, kWindowHideOnFullScreenAttribute); updatemodifiedmark(); } start_externals(); }