How do I get a Plymouth sprite to rotate? - linux

I'm working on a custom Plymouth splash for Kubuntu. I'm attempting to make an image rotate as the system is loading. I have tested it using both reboots and the X11 plugin and have been unsuccessful in both. Here's the .script file:
spiral_image = Image("Splash.png");
spiral_sprite = Sprite(spiral_image);
spiral_sprite.SetX(window.GetWidth() /2 - spiral_image.GetWidth() /2);
spiral_sprite.SetY(window.GetHeight() /2 - spiral_image.GetHeight() /2);
fun refresh_callback ()
{
time++;
theta = time / 100;
spiral_sprite.Rotate(theta);
}
Plymouth.SetRefreshFunction (refresh_callback);

You need to rotate the image, not the sprite:
fun refresh_callback () {
time++;
theta = time / 100;
spiral_sprite.SetImage( spiral_image.Rotate(theta) );
}
As per official documentation, in case anyone finds this question before they manage to find Plymouth documentation.
(Extra notes, slightly off-topic: Documentation says that default text colour is white. Don't count on that too much, it's black.)

Related

Why don't these lines have the same thickness? PIXI.JS

Let me ask you a question about PIXI.js. In Chrome, these lines looks like not the same thickness, but its the same Graphics API (lineTo, moveTo). Why is that?
let boxW = 46.5;
this.leftBox
.lineStyle(1, 0x000,1)
.beginFill(0xffffff)
.moveTo(0, 0)
.lineTo(465, 0)
.lineTo(465, 465)
.lineTo(0, 465)
.lineTo(0, 0)
.endFill();
for (let i = 1; i <= 9; i++) {
this.leftBox.moveTo(boxW * i, 0).lineTo(boxW * i, 465);
}
PAEz is right, it is likely anti aliasing.
When you create you Application anti-aliasing is turned off by default.
Try the below and see if it helps:
const app = new PIXI.Application({
'antialias': true,
'resolution': 2 // This may help too
});
// Add the view to the DOM
document.body.appendChild(app.view);
// ... your line code
The documentation for the Application class and its options can be found here:
https://pixijs.download/dev/docs/PIXI.Application.html
As a side note, PIXI is very fast but as your application scales anti-aliasing and resolution may have performance implications.
Finally to answer your question about what anti-aliasing is, in short, its a way to smooth out jagged edges on non-rectangular shapes, though you have a series lines it could help with your situation too. Here is an article that can tell you more: https://www.gamingscan.com/what-is-anti-aliasing/

Different wallpaper for each monitor in a multi-monitor setup in Windows 10

There are a number of questions and answers about setting wallpapers programmatically on multi-monitor setups in Windows, but I'm asking specifically for Windows 10 (and maybe Windows 8) because it seems to work differently from all the explanations I found.
Raymond Chen has an article "How do I put a different wallpaper on each monitor?" (https://devblogs.microsoft.com/oldnewthing/?p=25003), also quoted in Monitors position on Windows wallpaper. The core concepts is that Windows places the top-left corner of the provided bitmap at the top-left corner of the primary monitor, and wraps around to fill any desktop space to the left and/or above that. I understand that, I wrote a little program using that knowledge, and it works beautifully in Windows 7.
How it works: I create a bitmap that conceptually covers the whole desktop space, as the user sees it. I draw the contents of each monitor to that bitmap in its appropriate position (the program is written in C++ using VCL, but the principle remains the same in other programming environments):
TRect GetMonitorRect_WallpaperCoords(int MonitorNum)
{
Forms::TMonitor *PrimaryMonitor = Screen->Monitors[0];
Forms::TMonitor *Monitor = Screen->Monitors[MonitorNum];
// Get the rectangle in desktop coordinates
TRect Rect(Monitor->Left, Monitor->Top, Monitor->Left + Monitor->Width, Monitor->Top + Monitor->Height);
// Convert to wallpaper coordinates
Rect.Left += PrimaryMonitor->Left - Screen->DesktopLeft;
Rect.Top += PrimaryMonitor->Top - Screen->DesktopTop;
Rect.Right += PrimaryMonitor->Left - Screen->DesktopLeft;
Rect.Bottom += PrimaryMonitor->Top - Screen->DesktopTop;
return Rect;
}
std::unique_ptr<Graphics::TBitmap> CreateWallpaperBitmap_WallpaperCoords()
{
std::unique_ptr<Graphics::TBitmap> Bmp(new Graphics::TBitmap);
Bmp->PixelFormat = pf24bit;
Bmp->Width = Screen->DesktopWidth;
Bmp->Height = Screen->DesktopHeight;
// Draw background (not that we really need it: it will never be visible)
Bmp->Canvas->Brush->Style = bsSolid;
Bmp->Canvas->Brush->Color = clBlack;
Bmp->Canvas->FillRect(TRect(0, 0, Bmp->Width, Bmp->Height));
for (int MonitorNum = 0; MonitorNum < Screen->MonitorCount; ++MonitorNum)
{
TDrawContext DC(Bmp->Canvas, GetMonitorRect_WallpaperCoords(MonitorNum));
DrawMonitor(DC);
}
return Bmp;
}
(The draw context uses a coordinate translation rect so that the code int DrawMonitor function can draw in a rectangle like (0, 0, 1920, 1080) without having to wonder where in the full bitmap it is drawing, and with a clip rect so that DrawMonitor can not accidentally draw outside of the monitor it's drawing on).
Then I convert that bitmap to an image that will properly wrap around when placed at the top-left corner of the primary monitor (as Raymond Chen describes in his article):
std::unique_ptr<Graphics::TBitmap> ConvertWallpaperToDesktopCoords(std::unique_ptr<Graphics::TBitmap> &Bmp_WallpaperCoords)
{
std::unique_ptr<Graphics::TBitmap> Bmp_DesktopCoords(new Graphics::TBitmap);
Bmp_DesktopCoords->PixelFormat = Bmp_WallpaperCoords->PixelFormat;
Bmp_DesktopCoords->Width = Bmp_WallpaperCoords->Width;
Bmp_DesktopCoords->Height = Bmp_WallpaperCoords->Height;
// Draw Bmp_WallpaperCoords to Bmp_DesktopCoords at four different places to account for all
// possible ways Windows wraps the wallpaper around the left and bottom edges of the desktop
// space
Bmp_DesktopCoords->Canvas->Draw(Screen->DesktopLeft, Screen->DesktopTop, Bmp_WallpaperCoords.get());
Bmp_DesktopCoords->Canvas->Draw(Screen->DesktopLeft + Screen->DesktopWidth, Screen->DesktopTop, Bmp_WallpaperCoords.get());
Bmp_DesktopCoords->Canvas->Draw(Screen->DesktopLeft, Screen->DesktopTop + Screen->DesktopHeight, Bmp_WallpaperCoords.get());
Bmp_DesktopCoords->Canvas->Draw(Screen->DesktopLeft + Screen->DesktopWidth, Screen->DesktopTop + Screen->DesktopHeight, Bmp_WallpaperCoords.get());
return Bmp_DesktopCoords;
}
Then I install that bitmap as a wallpaper by writing the appropriate values in the registry and calling SystemParametersInfo with SPI_SETDESKWALLPAPER:
void InstallWallpaper(const String &Fn)
{
// Install wallpaper:
// There are 3 name/data pairs that have an effect on the desktop wallpaper, all under HKCU\Control Panel\Desktop:
// - Wallpaper (REG_SZ): file path and name of wallpaper
// - WallpaperStyle (REG_SZ):
// . 0: Centered
// . 1: Tiled
// . 2: Stretched
// - TileWallpaper (REG_SZ):
// . 0: Don't tile
// . 1: Tile
// We don't use the Wallpaper value itself; instead we use SystemParametersInfo to set the wallpaper.
// The file name needs to be absolute!
assert(Ioutils::TPath::IsPathRooted(Fn));
std::unique_ptr<TRegistry> Reg(new TRegistry);
Reg->RootKey = HKEY_CURRENT_USER;
if (Reg->OpenKey(L"Control Panel\\Desktop", false))
{
Reg->WriteString(L"WallpaperStyle", L"1");
Reg->WriteString(L"TileWallpaper", L"1");
Reg->CloseKey();
}
SystemParametersInfoW(SPI_SETDESKWALLPAPER, 1, Fn.c_str(), SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
}
But when I test it in Windows 10, it doesn't work properly anymore: Windows 10 puts the wallpaper completely in the wrong place. Seeing as other people have asked questions about multi-monitor wallpapers in the past, I'm hoping there are people with experience of it on Windows 10.
As far as I can see, Windows 10 places the top-left corner of the provided bitmap at the top-left corner of the desktop space (by which I mean the bounding rectangle of all monitors), instead of the top-left corner of the primary monitor. In code, that means: I leave out the ConvertWallpaperToDesktopCoords step, and then it works fine as far as I can see.
But I can't find any documentation on this, so I don't know if this is officially explanation of how Windows 10 does it. Use with care. Also I don't know when this different behavior started: in Windows 10, or maybe earlier in Windows 8.

Chrome capture visible tab gives messy result

I have a Chrome extension, where I'm using the captureVisibleTab method of the chrome.tabs API to capture screenshots. I have tested the extension on 3 devices (Chromebooks) and I'm getting mixed results. Two of them work perfectly, but one always returns a completely malformed screenshot.
My code:
chrome.tabs.onUpdated.addListener(function(tabId,changeInfo,tab){
chrome.tabs.get(tabId, function (_tab) {
if (_tab.status == "complete" && _tab.active ) {
chrome.tabs.captureVisibleTab( function(dataUrl){
});
}
});
});
Any ideas what could be the issue on that one device?
EDIT
Example of a bad screenshot:
I suspect that the device pixel ratio is higher on your 3rd device. This was an issue I was having with Retina displays when building a screenshot app. Basically, certain high-resolution displays have a higher ratio pixels per square inch. You're going to want to find window.devicePixelRatio and divide the context scale by that amount.
Assuming that you are using Canvas to draw the screenshot and capture it into an image, this little snippet should help show what you're going to want to do:
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext("2d");
if(window.devicePixelRatio > 1){
context.scale(1/window.devicePixelRatio, 1/window.devicePixelRatio);
}
context.drawImage(image, 0, 0);
Let me know if that works for you.

NSSplitViewItem collapse animation and window setFrame conflicting

I am trying to make a (new in 10.10) NSSplitViewItem collapse and uncollapse whilst moving its containing window so as to keep the whole thing "in place".
The problem is that I am getting a twitch in the animation (as seen here).
The code where I'm doing the collapsing is this:
func togglePanel(panelID: Int) {
if let splitViewItem = self.splitViewItems[panelID] as? NSSplitViewItem {
// Toggle the collapsed state
NSAnimationContext.runAnimationGroup({ context in
// special case for the left panel
if panelID == 0 {
var windowFrame = self.view.window.frame
let panelWidth = splitViewItem.viewController.view.frame.width
if splitViewItem.collapsed {
windowFrame.origin.x -= panelWidth
windowFrame.size.width += panelWidth
} else {
windowFrame.origin.x += panelWidth
windowFrame.size.width -= panelWidth
}
self.view.window.animator().setFrame(windowFrame, display: true)
}
splitViewItem.animator().collapsed = !splitViewItem.collapsed
}, completionHandler: nil)
}
}
I am aware of the "Don't cross the streams" issue (from session 213, WWDC'13) where a window resizing animation running on the main thread and a core animation collapse animation running on a separate thread interfere with each other. Putting the splitViewItem collapse animation onto the main thread seems like the wrong approach and I've got a nagging feeling there's a much better way of doing this that I'm missing.
Since I am not finding any documentation on the NSSplitViewItems anywhere (yet) I would appreciate any insights on this.
I have the little test project on GitHub here if anyone wants a look.
Update The project mentioned has now been updated with the solution.
Thanks,
Teo
The problem is similar to the "don't cross the streams" issue in that there are two drivers to the animation you've created: (1) the split view item (2) the window, and they're not in sync.
In the example from the '13 Cocoa Animations talk, constraints were setup to result in the correct within-window animation as only the window's frame was animated.
Something similar could be tried here -- only animating the window's frame and not the split view item, but since the item manages the constraints used to (un)collapse, the app can't control exactly how within-window content animates:
Instead the split view item animation could completely drive the animation and use NSWindow's -anchorAttributeForOrientation: to describe how the window's frame is affected.
if let splitViewItem = self.splitViewItems[panelID] as? NSSplitViewItem {
let window = self.view.window
if panelID == 0 {
// The Trailing edge of the window is "anchored", alternatively it could be the Right edge
window.setAnchorAttribute(.Trailing, forOrientation:.Horizontal)
}
splitViewItem.animator().collapsed = !splitViewItem.collapsed
}
For anyone using Objective C and targeting 10.11 El Capitan.
This did the trick for me, didn't need to set AnchorAttributes.
splitViewItem.collapsed = YES;

Display Text on MFC Based Application

I'm a little new to using MFC and VC++ as such, but I'm doing this as part of a Course and i Have to stick to VC++.
http://www.cprogramming.com/tutorial/game_programming/same_game_part1.html
This is the tutorial I have been following to make a simple samegame. However when i try to display score, the score is getting displayed Underneath or outside my application window, even though I've displayed score before calling updateWindow(). I've tried various methods but I am kinda lost here.
Here is the code I'm using to Display the score:
void CSameGameView::updateScore()
{
CSameGameDoc* pDoc = GetDocument();
CRect rcClient, rcWindow;
GetClientRect(&rcClient);
GetParentFrame()->GetWindowRect(&rcWindow);
int nHeightDiff = rcWindow.Height() - rcClient.Height();
rcScore.top=rcWindow.top + pDoc->GetHeight() * pDoc->GetRows() + nHeightDiff;
rcScore.left=rcWindow.left + 50;
rcScore.right=rcWindow.left + pDoc->GetWidth() - 50;
rcScore.bottom=rcScore.top + 20;
CString str;
double points = Score::getScore();
str.Format(_T("Score: %0.2f"), points);
HDC hDC=CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL);
COLORREF clr = pDoc->GetBoardSpace(-1, -1); //this return background colour
pDC->FillSolidRect(&rcScore, clr);
DrawText(hDC, (LPCTSTR) str, -1, (LPRECT) &rcScore, DT_CENTER);
}
Thank you for any help and I'm sorry if the question doesn't make sense or in ambiguous.
There are several problems with your code:
1. The hDC you are creating is going to have coordinates relative to the desktop window. To paint text in your window, use CClientDC like this: CClientDC dc(this); (see http://msdn.microsoft.com/en-US/library/s8kx4w44%28v=vs.80%29.aspx)
2. The code you have will leak a DC every time the function is called. The method in #1 will fix that.
3. Your paint code should be done in the CView::OnDraw. There you get a DC passed to you and you don't have to worry about creating one with CClientDC. Set the variables you want to draw (e.g. your points or score), store them as class members and draw them in CView::OnDraw.
Don't do the drawing in your updateScore method.
Make sense? Hang in there!

Resources