Firefox Add-On Development - Add Item to Right Click on Tab - firefox

I had an idea for an add on that would require me to add an item/menu-item to a tab when someone right clicks on it. How would I implement this? I have no Firefox Add-On experience and I just had an idea that is simple, yet I thought would be cool.

Use window.document.getElementById("tabContextMenu") to manipulate tab's menu.
Here is code of New Tab in Tab Context Menu
let _ = require("l10n").get;
let winUtils = require("window-utils");
let { isBrowser } = require("api-utils/window/utils");
var delegate = {
onTrack: function (window) {
if (isBrowser(window) ){
let menu = window.document.getElementById("tabContextMenu");
let newtab = window.document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul","menuitem");
newtab.setAttribute("id", "contexttab-newtab");
newtab.setAttribute("label", _("newtab_string"));
newtab.setAttribute("accesskey", _("newtabaccesskey_string"));
newtab.setAttribute("oncommand", "BrowserOpenTab();");
menu.insertBefore(newtab, menu.firstChild);
} // End isBrowser
} // End ontrack
} // End delegate function
let tracker = new winUtils.WindowTracker(delegate);

Related

Design Preamble Mac OS X Mas

I recently packaged my app for MAC Store and was rejected. Below is the message sent to me by review team. When i testing using development mode everything works fine but I can't picture where i am getting something wrong. Any idea would be appreciated. App was built using Electron.
Design Preamble
The user interface of your app is not consistent with the macOS Human
Interface Guidelines.
Specifically, we found that when the user closes the main application
window there is no menu item to re-open it.
Next Steps
It would be appropriate for the app to implement a Window menu that
lists the main window so it can be reopened, or provide similar
functionality in another menu item. macOS Human Interface Guidelines
state that "The menu bar [a]lways contains [a] Window menu".
Alternatively, if the application is a single-window app, it might be
appropriate to save data and quit the app when the main window is
closed.
For information on managing windows in macOS, please review the
following sections in Apple Human Interface Guidelines:
The Menu Bar and Its Menus
The Window Menu
The File Menu
Clicking in the Dock
Window Behavior
Please evaluate how you can
implement the appropriate changes, and resubmit your app for review.
The Problem is that after the Application is minimized by pressing the x button, there is no way for the user to open it again from the dock.
One way to fix this is to just terminate the Application when the x button is clicked.
I had the same issue and fixed it by adding this function in AppDelegate. This solution is for Swift 4.2
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true
}
Now the Application terminates, when the x button is clicked.
If you are working with Xamarin, edit your AppDelegate.cs to create a menu to reopen the main window:
public class AppDelegate : FormsApplicationDelegate
{
NSWindow window;
public override NSWindow MainWindow
{
get
{
return window;
}
}
public AppDelegate()
{
var style = NSWindowStyle.Closable | NSWindowStyle.Resizable | NSWindowStyle.Titled;
var rect = new CoreGraphics.CGRect(100, 100, 1024, 768);
window = new NSWindow(rect, style, NSBackingStore.Buffered, false);
window.TitleVisibility = NSWindowTitleVisibility.Hidden;
}
private NSMenu MakeMainMenu()
{
// top bar app menu
NSMenu menubar = new NSMenu();
NSMenuItem appMenuItem = new NSMenuItem();
menubar.AddItem(appMenuItem);
NSMenu appMenu = new NSMenu();
appMenuItem.Submenu = appMenu;
// add separator
NSMenuItem separator = NSMenuItem.SeparatorItem;
appMenu.AddItem(separator);
// add open menu item
string openTitle = String.Format("Open {0}", "MyApp");
var openMenuItem = new NSMenuItem(openTitle, "o", delegate
{
// Get new window
window.MakeKeyAndOrderFront(this);
});
appMenu.AddItem(openMenuItem);
// add quit menu item
string quitTitle = String.Format("Quit {0}", "MyApp");
var quitMenuItem = new NSMenuItem(quitTitle, "q", delegate
{
NSApplication.SharedApplication.Terminate(menubar);
});
appMenu.AddItem(quitMenuItem);
return menubar;
}
public override void DidFinishLaunching(NSNotification notification)
{
// finally add menu
NSApplication.SharedApplication.MainMenu = MakeMainMenu();
// Insert code here to initialize your application
Forms.Init();
//Load Application
LoadApplication(new App());
//Did Finish Launching
base.DidFinishLaunching(notification);
}
public override void WillTerminate(NSNotification notification)
{
// Insert code here to tear down your application
}
}
If you are workwing with Cocoa do the same but in the specific language.
Reopen the window with this instruction:
[window makeKeyAndOrderFront:self];
For electron apps you can add this code to your index.js or main.js to resolve the issue:
app.on('window-all-closed', () => {
app.quit();
});

Drag and drop function swift OSX

This is a bit complex but I hope that someone can help me.
I am trying to build a drag and drop function for my OSX application.
This is how it is looking at the moment.
So there is just a single textfield which the user can drag and drop around the view. It is simple enough with just one textfield but if there are several textfields it is getting complicated and I don't know how to approach.
This is what I currently have:
#IBOutlet weak var test: NSTextField!
#IBAction override func mouseDragged(theEvent: NSEvent) {
NSCursor.closedHandCursor().set()
var event_location = theEvent.locationInWindow
test.frame.origin.x = event_location.x - 192
test.frame.origin.y = event_location.y
}
Test is the name of my NSTextField. I know the name of it so it is simple to move it arround. But if the user adds more textfields (see on the left pane) then I don't know how to address this textfield because I have no name of it (like "test" for the first input).
I am adding the textfields via this code:
let input = NSTextField(frame: CGRectMake(width, height, 100, 22))
self.MainView.addSubview(input)
How can I determine which textfield (if there are multiple on the view) was selected and then move the appropriate via drag and drop?
The drag and drop is working for that single static textfield
I have prepared a sample app, so consider this:
https://github.com/melifaro-/DraggableNSTextFieldSample
The idea is to introduce SelectableTextField which inherits NSTextField. SelectableTextField provides facility for subscription of interested listener on text field selection event. It has didSelectCallback block variable, where you need to set you handling code. Something like this:
textField.didSelectCallback = { (textField) in
//this peace of code will be performed once mouse down event
//was detected on the text field
self.currentTextField = textField
}
By using mentioned callback mechanism, once text field selected, we can store it in currentTextField variable. So that when mouseDragged function of ViewController is called we are aware of currentTextField and we can handle it appropriatelly. In case of sample app we need adjust currentTextField origin according drag event shift. Hope it became better now.
P.S. NSTextField is opened for inheriting from it, so you can freely use our SelectableTextField everywhere where you use NSTextField, including Interface Builder.
EDIT
I have checked out your sample. Unfortuantly I am not able to commit /create pull request into you repository, so find my suggestion here:
override func viewDidLoad() {
super.viewDidLoad()
didButtonSelectCallback = { (button) in
if let currentButton = self.currentButton {
currentButton.highlighted = !currentButton.highlighted
if currentButton == button {
self.currentButton = nil
} else {
self.currentButton = button
}
} else {
self.currentButton = button
}
button.highlighted = !button.highlighted
}
addButtonAtRandomePlace()
addButtonAtRandomePlace()
didButtonSelectCallback(button: addButtonAtRandomePlace())
}
override func mouseDragged(theEvent: NSEvent) {
guard let button = currentButton else {
return
}
NSCursor.closedHandCursor().set()
button.frame.origin.x += theEvent.deltaX
button.frame.origin.y -= theEvent.deltaY
}
private func addButtonAtRandomePlace() -> SelectableButton {
let viewWidth = self.view.bounds.size.width
let viewHeight = self.view.bounds.size.height
let x = CGFloat(rand() % Int32((viewWidth - ButtonWidth)))
let y = CGFloat(rand() % Int32((viewHeight - ButtonHeight)))
let button = SelectableButton(frame: CGRectMake(x, y, ButtonWidth, ButtonHeight))
button.setButtonType(NSButtonType.ToggleButton)
button.alignment = NSCenterTextAlignment
button.bezelStyle = NSBezelStyle.RoundedBezelStyle
button.didSelectCallback = didButtonSelectCallback
self.view.addSubview(button)
return button
}

How can this code make a new image appear on each click - Scala

What I am looking to do is have a button click create and load a new image to the panel. The image should be draggable as well as for me able to find its position on screen etc. Im not sure how to do this. The idea being after multiple clicks I will have multiple new images all able to drag and move about.
The code looks something like this :-
val top = new MainFrame {
//General code for menus
val button = new Button {
text = "Click for Image"
}
val panel = new Panel {
override def paint(g:Graphics2D){
}
listenTo (button
mouse.clicks,
mouse.moves)
reactions += {
case ButtonClicked(`button`) => {
new ImagePanel{ imagePath = ("bottoming.jpg")}
}
case e: MousePressed =>{}
case e: MouseDragged =>{}
case e: MouseReleased =>{}
}
}
import BorderPanel.Position._
contents =
new BorderPanel {
layout += new Label("label") -> North
layout += panel -> Center
layout += button -> West
}
}

How to programmatically move a tab to another window in a firefox Addon-SDK extension?

While it looks like you can change the order of a tab within a window by updating the tab .index property, it doesn't look like the tabs api directly supports the move of a tab to another window.
Am I missing something? Is there a viable workaround?
It is possible through the low level module window/utils. The example below duplicates the active tab across every open window
const { getMostRecentBrowserWindow, windows: getWindows } = require("sdk/window/utils");
const { ActionButton } = require("sdk/ui/button/action");
var button = ActionButton({
id: "duplicatetab-button",
label: "Duplicate tab",
icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACUElEQVQ4jaWTTWtTURCGjzc33CCpbVKN4kexC9EUY1Hov+iqPyDrbgtuCrViKUERqsWVguBGQaW4UiKiaEVxoShFGgnuBMUqNW3zce49Z+ZxUWtwoRR8YXbzPswM7xj+JgVEiXGsYVknxgII4Ltt5p8AB8RArOAUVQfqQJNtAFA8QgvF6i9PR1Dt0KbVBTjncM4hIni/OZv3HsRB+wvefiP2LcQnJIkQe49FEJFNQLPZZHh4mEwmQyqVoqenh3K5TGvlK1dOlageH+HG4DFar1/S0A6Lr99xdN8QxWKRXC6HGR0dJZvNMjk5Sb1ep1gskk6nuTo/D+/ec7dvkBdhP9cKeX7UXxEZQ2/YRxRFLC8vY+bm5qhUKnjvsdYyPj5OFEWcnTnHujiS5TfcPDbAw50h9w7u5f7UadLZFLVaDRHBiGzuY61lbGyMXC5HoVBgrbGGWAW/TvvxHR7s7udFKs/1oyfZ+PSRTqeDqm7eoFqtEoYhmUyG2dlZVJU4iREfI/WP3Nt9iMUdu7jdf5Anly5i0oaVlRWazSZmYWGBIAiIoohyucz09DQTExPMnJli9dlT5vcM8Kh3gFsHDuNqb9mb7yXMRBhjWFpawpRKJVKpFMYYgiAgDEOCIOD81BkunBjh8pEhKqUhGkvP6bQ/U//wgUP5/YRhSDabxbTbbVQV5xyq2q0kgR8NdOM7JKuo/Y5qggqIdPvMlnkrQCKCquJFsOrxeHAJxA48eFU6Xv4EqOpv41YqnQirqliv4MEmQtN7RBSs7wL+/gvb038DfgJnyUabbHzUbQAAAABJRU5ErkJggg==",
onClick: function() {
var xulwindows = getWindows("navigator:browser");
var xulactivewindow = getMostRecentBrowserWindow();
var xulactivetab = xulactivewindow.gBrowser.selectedTab;
xulwindows.forEach(function(win){
if(win === xulactivewindow)
return;
var duplicatedtab = win.gBrowser.duplicateTab(xulactivetab);
win.gBrowser.moveTabTo(duplicatedtab, 0); // the second argument is the index
});
}
});
#paa's solution is nice but it doesn't move a tab. His is duplicating the tab. So flash movies will not retain their position etc. And its not a move its a duplicatio, like he explained.
I did a lot of research was real fun. The way they move tabs in Firefox is via docShell swapping. This will accomplish what you want. It's written for bootstrap though so needs touch up for addon sdk.
Pass second argument as string of tabbed or non-tabbed if you want to move it to a new window. Else pass second argument an existing window and it will be moved there. can copy paste and run this code from sratchpad.
this uses the gBrowser.swapBrowsersAndCloseOther function
function moveTabToWin(aTab, tDOMWin) {
//tDOMWin means target DOMWindow means the window you want the tab in
//if tDOMWin == 'tabbed' or == 'non-tabbed' it opens in a new window
//if aTopContWin is the last in its window, then its window is closed
if (tDOMWin == 'tabbed' || tDOMWin == 'non-tabbed') {
var sa = Cc["#mozilla.org/supports-array;1"].createInstance(Ci.nsISupportsArray);
var wuri = Cc["#mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
wuri.data = 'about:blank';
sa.AppendElement(wuri);
let features = "chrome,dialog=no";
if (tDOMWin == 'tabbed') {
features += ',all';
}
var sDOMWin = aTab.ownerGlobal; //source DOMWindow
if (PrivateBrowsingUtils.permanentPrivateBrowsing || PrivateBrowsingUtils.isWindowPrivate(sDOMWin)) {
features += ",private";
} else {
features += ",non-private";
}
var XULWindow = Services.ww.openWindow(null, 'chrome://browser/content/browser.xul', null, features, sa);
XULWindow.addEventListener('load', function() {
var DOMWindow = XULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
DOMWindow.gBrowser.selectedTab.linkedBrowser.webNavigation.stop(Ci.nsIWebNavigation.STOP_ALL);
DOMWindow.gBrowser.swapBrowsersAndCloseOther(DOMWindow.gBrowser.selectedTab, aTab);
//DOMWindow.gBrowser.selectedTab = newTab;
}, false);
} else if (tDOMWin) {
//existing dom window
var newTab = tDOMWin.gBrowser.addTab('about:blank');
newTab.linkedBrowser.webNavigation.stop(Ci.nsIWebNavigation.STOP_ALL);
tDOMWin.gBrowser.swapBrowsersAndCloseOther(newTab, aTab);
tDOMWin.gBrowser.selectedTab = newTab;
}
}
moveTabToWin(gBrowser.selectedTab, 'tabbed');
I'v got inspired by #Noitidart's answer and came up with my solution.
I'm adding setWindow(window, index) method to Tab's prototype, so that any SDK tab can be moved to another window from anywhere in the addon with a simple call like this:
browserWindows[0].activeTab.setWindow(browserWindows.activeWindow, 0);
This will move active tab of window 0 to the beginning of active window.
And here is the method:
Update:
I've put together a module to do exactly this: jetpack-tab-setwindow
Old solution (breaks in FF43)
var Tab = require("sdk/tabs/tab").Tab;
Tab.prototype.setWindow = function (window, index) {
var tab = this;
var oldWindow = tab.window;
if ( oldWindow !== window ) {
// We have to use lower-level API here
var Ci = require('chrome').Ci;
var viewFor = require("sdk/view/core").viewFor;
var aTab = viewFor(tab);
var aWin = viewFor(window);
var gBrowser = aWin.gBrowser;
// Get tab properties
var isSelected = oldWindow.activeTab == tab;
var isPinned = aTab.pinned;
// Log for debugging:
var tabId = tab.id;
console.log('setWindow', {index, isSelected, isPinned, tab, tabId});
// Create a placeholder-tab on destination windows
var newTab = gBrowser.addTab('about:newtab');
newTab.linkedBrowser.webNavigation.stop(Ci.nsIWebNavigation.STOP_ALL); // we don't need this tab anyways
// If index specified, move placeholder-tab to desired index
if ( index != undefined ) {
var length = gBrowser.tabContainer.childElementCount;
if ( index < 0 ) index = length - index;
if( 0 <= index && index < length ) {
gBrowser.moveTabTo(newTab, index);
}
}
// Copy tab properties to placeholder-tab
if ( isPinned ) {
gBrowser.pinTab(newTab);
}
// For some reason this doesn't seem to work :-(
if ( isSelected ) {
gBrowser.selectedTab = newTab;
}
// Swap tabs and remove placeholder-tab
gBrowser.swapBrowsersAndCloseOther(newTab, aTab);
}
};

Firefox extension, opening a local file in a new foreground tab from menu

I am learning how to program Firefox extensions. I have created a new menu and when the menu item is clicked, I want a new tab to be opened, in the foreground, containing a local file contained within the contents directory.
For example:
MENU -> Item1
When Item1 is selected, I want a new tab to open in the foreground containing what is located in /myextension/content/content.html.
Where can I find out how to do this?
For clarity, I can get the local file to open in a new tab, I just do not know how to get to open in a new focused tab.
I use the following function to open a tab, make sure it hasn't already been opened and switch focus to it:
function OpenAndReuseOneTabPerURL(url)
{
var wm = Components.classes["#mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator);
var browserEnumerator = wm.getEnumerator("navigator:browser");
// Check each browser instance for our URL
var found = false;
while (!found && browserEnumerator.hasMoreElements())
{
var browserWin = browserEnumerator.getNext();
var tabbrowser = browserWin.gBrowser;
// Check each tab of this browser instance
var numTabs = tabbrowser.browsers.length;
for (var index = 0; index < numTabs; index++)
{
var currentBrowser = tabbrowser.getBrowserAtIndex(index);
if (url == currentBrowser.currentURI.spec)
{
// The URL is already opened. Select this tab.
tabbrowser.selectedTab = tabbrowser.tabContainer.childNodes[index];
// Focus *this* browser-window
browserWin.focus();
found = true;
break;
}
}
}
// Our URL isn't open. Open it now.
if (!found)
{
var recentWindow = wm.getMostRecentWindow("navigator:browser");
if (recentWindow) {
// Use an existing browser window
recentWindow.delayedOpenTab(url, null, null, null, null);
} else {
// No browser windows are open, so open a new one.
window.open(url);
}
}
}
Use it like:
OpenAndReuseOneTabPerURL("http://yoururl.com");

Resources