Gnome Shell Extension: Resize and position a window on creation - gnome-shell

I am trying to write a Gnome Shell extension that resizes and positions a window when it is created. I am using the move_resize_frame method provided by the Meta.Window object to set the window's size and position, and I've also tried move and move_resize_frame. However, while the window is sized correctly, it is not being positioned correctly, and it seems that the window manager is applying some constraints on the window position. The window is not maximized.
Here is the code I am using:
let windowCreatedId, sizeChangedId;
function init() {
}
function enable() {
windowCreatedId = global.display.connect('window-created', onWindowCreated);
}
function disable() {
global.display.disconnect(windowCreatedId);
if (sizeChangedId)
global.display.disconnect(sizeChangedId);
}
function onWindowCreated(display, win) {
sizeChangedId = win.connect('size-changed', onSizeChanged);
resizeWindow(win);
}
function onSizeChanged(win) {
resizeWindow(win);
}
function resizeWindow(win) {
win.move_resize_frame(false, 20, 20, 2000, 2000);
}
What am I missing or what should I change to make this extension work properly?

Instead of the size-changed signal, you need to connect to the first-frame signal, which is triggered when the frame is first drawn on the screen.
Here's a full implementation:
const Meta = imports.gi.Meta;
let windowCreatedId;
function init() {
}
function enable() {
windowCreatedId = global.display.connect('window-created', onWindowCreated);
}
function disable() {
global.display.disconnect(windowCreatedId);
}
function onWindowCreated(display, win) {
const act = win.get_compositor_private();
const id = act.connect('first-frame', _ => {
resizeWindow(win);
act.disconnect(id);
});
}
function resizeWindow(win) {
win.move_resize_frame(false, 20, 20, 2000, 2000);
}
It uses the window's get_compositor_private() method, which feels a little iffy, but it works (and Material Shell uses it too...)

Related

SPFx: How to re-render my WebPart on section layout change

I'm trying to make my WebPart responsive to the column width in my section layout.
I get the width of the bounding rectangle by calling
const width: number = this.domElement.getBoundingClientRect().width;
My render-function looks like this:
public render(): void {
const width: number = this.domElement.getBoundingClientRect().width;
this.domElement.innerHTML = `<div>${width}</div>`;
}
When I insert my WebPart into the SharePoint workbench, the number 736 is shown.
However, if I change the layout of the section from one column to something else, the number doesn't change.
What do I need to do to trigger the render function as soon as the layout (and therefor the width) changes?
To do that you can create an event listener and in your function set the state to re-render your webpart:
private handleWindowSizeChange() {
this.setState({
size: window.innerWidth
});
}
public componentDidMount() {
window.addEventListener('resize', this.handleWindowSizeChange.bind(this));
}
public componentWillUnmount() {
window.removeEventListener('resize', this.handleWindowSizeChange.bind(this));
}
I have used the ResizeObserver api to listen for the layout change in the layout.
The only problem is that it is not supported by IE, Edge, and Safari.
public componentDidMount() {
if(window.ResizeObserver) {
this.resizeObserver = new ResizeObserver(this.handleResize);
this.resizeObserver.observe(this.domElement)
}
}
public componentWillUnmount() {
if(window.ResizeObserver) {
this.resizeObserver.disconnect()
}
}

Xamarin - Make rotations with CoreGraphics.CGAffineTransform

I want to make a UI Image rotate while content is downloading and I can't seem to make it rotate.
I have this event:
public override void ViewDidAppear(bool animated)
{
NoConnectionView.Hidden = CheckConnectivityStatus();
Task.Run(async () => await StartSpinningAnimation(true));
}
Which then fires this method:
protected async Task StartSpinningAnimation(bool IsSpinning)
{
do
{
UpdateActiveImage.Transform = CoreGraphics.CGAffineTransform.MakeRotation((float)Math.PI / 4);
}
while (IsSpinning);
return;
}
The page will eventually change after files are downloaded so I just want it to spin forever. It does animate at all. Does anyone have any ideas?
Using C# and Xamarin.iOS to develop iOS is a letter bit different from the Native language, Whenever you want to invoke some UI element in your background thread(like you need make some UI do an animation), you must use:
InvokeOnMainThread(delegate {
//Do something related UI stuff
});
If you add a try catch for it, you will get the exception like that "You are calling a method that can only be invoked in UI thread";
And by the way, you can not just use a do while to make an animation, I write a sample for you, you can take a look:
public partial class ViewController : UIViewController
{
bool needAnimate = true;
int count = 0;
UIView animationView = new UIView();
public ViewController (IntPtr handle) : base (handle)
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Perform any additional setup after loading the view, typically from a nib.
animationView.Frame = new CoreGraphics.CGRect (50, 50, 100, 100);
animationView.BackgroundColor = UIColor.Red;
this.Add (animationView);
this.View.AddGestureRecognizer (new UITapGestureRecognizer (() => {
Task.Run(async () => await StartAnimation());
}));
}
private async Task StartAnimation()
{
do
{
Console.WriteLine ("count = " + count++);
InvokeOnMainThread(delegate {
UIView.Animate(0.25,delegate {
animationView.Transform = CoreGraphics.CGAffineTransform.MakeRotation((float)Math.PI / 4 * (count/4 + 1));
});
});
System.Threading.Thread.Sleep(250);
}
while (needAnimate);
return;
}
public override void DidReceiveMemoryWarning ()
{
base.DidReceiveMemoryWarning ();
// Release any cached data, images, etc that aren't in use.
}
}
The animation is not smoothly, you need to optimize it yourself.
If you still have some questions, just leave here, I will check it latter.
Hope it can help you and welcome to Xamarin.
I would use UIView.AnimateNotify to perform the animation with CoreGraphics and totally avoid spin-loops to do something like this.
Example that spins an image 180 degrees and back repeating forever until stopped:
bool _animateStopping = false;
protected void SpinningAnimation(bool animate)
{
if (_animateStopping) return;
_animateStopping = !animate;
if (animate)
{
UIView.AnimateNotify(1,
() =>
{
image.Transform = CGAffineTransform.MakeRotation((nfloat)(Math.PI)); // in one second, spin 180 degrees
},
(bool finished) =>
{
UIView.AnimateNotify(1,
() =>
{
image.Transform = CGAffineTransform.MakeRotation(0); // in one second, spin it back
},
(bool finished2) =>
{
SpinningAnimation(true);
});
});
}
else {
UIView.AnimateNotify(1,
() =>
{
image.Alpha = 0; // fade away in one second
},
(bool finished) =>
{
image.RemoveFromSuperview();
_animateStopping = false;
}
);}
}
Usage:
image = new UIImageView(new CGRect(100, 100, 100, 100));
image.Image = UIImage.FromFile("wag.png");
Add(image);
SpinningAnimation(true);
await Task.Delay(5000); // simulate performing downloads, when done stop the animiation
SpinningAnimation(false);

Tracking frames and/or time during an animation

Can I call a function(one that will make another object visible/invisible) on a specific animation frame or time? I would like to have arrows describe the movement of the animation at certain times during the animation. While I can just make them visible when I start the animation and make them invisible when the animation stops, I would like to specify ranges inside the animation to do this
playPatientAnim: function (anim, callback) {
var pending = 1;
var me = this;
var finish = callback ? function () {
if (pending && !--pending) {
callback.call(me, anim);
}
} : null;
me.currentPatient.skinned.forEach(function (mesh) {
mesh.animations.forEach(function(anim){
anim.stop();
});
});
me.currentPatient.skinned.forEach(function (mesh) {
var animation = mesh.animations[anim];
animation.stop();
if (animation) {
pending++;
animation.onComplete = finish;
animation.play();
}
});
if (finish) {
finish();
}
}
You can make a mesh visible or invisible ( mesh.visible = false; //or true ). To change visibility at certain time you could use timestamp:
new Date().getTime() and calculate how you want to do the sequence of your animation.

Actionscript MouseScroll / MouseDrag

Is there a "MouseScroll" or "MouseDrag" Event in Actionscript, I could not find something properly.
I have this:
resultPumpVolCalcBoxQv.addEventListener(MouseEvent.CLICK, getPumpVolumenQv);
resultPumpVolCalcBoxQn.addEventListener(MouseEvent.CLICK, getPumpVolumenn);
resultPumpVolCalcBoxQvng.addEventListener(MouseEvent.CLICK, getPumpVolumenng);
function getPumpVolumenQv(e:MouseEvent):void {
pumpeVolQv = Number(pumpeVolumenstromTextFieldqv.text);
pumpeVolN = Number(pumpeVolumenstromTextFieldn.text);
pumpeVolNg = Number(pumpeVolumenstromTextFieldng.text);
if(pumpeVolumenstromTextFieldng.text != null && pumpeVolumenstromTextFieldn.text != null) {
totalqv = (pumpeVolNg * pumpeVolN)/1000
pumpeVolumenstromTextFieldqv.text = " " + totalqv;
} else {
//
}
}
Currently this works with a click event.
I want to make this calculation happen if I drag something like a scrollbar.
You have to combine the usage of MouseDown and MouseOut to create a drag outcome
obj.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
obj.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
function mouseDown($e:MouseEvent):void{
MovieClip($e.currentTarget).startDrag();
}
function mouseUp($e:MouseEvent):void{
MovieClip($.currentTarget).stopDrag();
}
If you want it to constrain to an X or Y position, add a rectangular box paraments in the startDrag() functions
You will have to use the Mouse up and Mouse down events to achieve this. However, be careful to add and then remove the event listeners when they are not needed. This way you will ensure that the event listeners are properly removed and not added multiple times causing memory issues.
private var yourObject:MovieClip;
private function addDragListeners():void
{
yourObject.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown, false, 0, true);
yourObject.addEventListener(MouseEvent.MOUSE_DOWN, onMouseUp, false, 0, true);
}
private function removeDragListeners():void
{
yourObject.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
yourObject.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseUp);
}
protected function onMouseDown(e:MouseEvent):void
{
yourObject.startDrag();
}
protected function onMouseUp(e:MouseEvent):void
{
yourObject.stopDrag();
}
You can look into the startDrag() method in case you need to add some bounds for the dragging.

javafx close window

I have a javafx app, and I was able to spawn another window, but I can't seem to find a way to close the the window i started in.
I used this to load the second window
var design = Launcher {};
javafx.stage.Stage
{
title: "Launcher"
scene: design.getDesignScene ()
}
stage.close(), but you would need a variable that references the original stage.
The way it worked for me:
I have the Main.fx where I instante the window I want to see first.
ex:
var mainWind:MainWindow = MainWindow{ };
MainWindow.fx will extend CustomNode and override create() method.
In the create() method I have the stage
ex:
public class MainWindow extends CustomNode{
...
var stage:Stage;
override function create():Node {
var n:Node;
stage = Stage {
width: 300
height: 180
title: "Login"
scene: Scene {
content:[ userText, userTextBox, passwdText, passwdTextBox, btnsBox ]
}
}
return n;
}
}
In MainWindow.fx I have a button with an event where I close this stage and show the other one .
ex:
Button {
text: "Login"
font:Font{ name:"Arial" size: 12}
layoutInfo:LayoutInfo {
width: loginbtn_width
}
blocksMouse: false
//close main window
onMouseClicked: function(e:MouseEvent):Void { stage.close(); }
//open the other window
action: function(){
// the ConnectionSettings will also extend CustomNode and will have its own stage
var conSetWind:ConnectionSettings = ConnectionSettings{ };
}
}
Iulia

Resources