mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 695152 - Tabs tray implementation for native UI. r=mfinkle
--HG-- extra : rebase_source : 81efd1c8844a1ecdf49be1ee28060c4e8198e23d
This commit is contained in:
parent
dedcb28dbb
commit
03c42af896
@ -143,15 +143,5 @@
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name="org.mozilla.gecko.ShowTabs"
|
||||
android:theme="@android:style/Theme.Translucent"
|
||||
android:windowSoftInputMode="stateUnspecified|adjustResize"
|
||||
android:windowIsTranslucent="true"
|
||||
android:windowContentOverlay="@null"
|
||||
android:windowNoTitle="true"
|
||||
android:windowIsFloating="true"
|
||||
android:backgroundDimEnabled="false">
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
|
@ -56,8 +56,8 @@ import org.mozilla.gecko.R;
|
||||
public class BrowserToolbar extends LinearLayout {
|
||||
final private ProgressBar mProgressBar;
|
||||
final private Button mAwesomeBar;
|
||||
final private Button mTabs;
|
||||
final private ImageButton mFavicon;
|
||||
final private ImageButton mReloadButton;
|
||||
|
||||
public BrowserToolbar(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
@ -77,22 +77,27 @@ public class BrowserToolbar extends LinearLayout {
|
||||
}
|
||||
});
|
||||
|
||||
mFavicon = (ImageButton) findViewById(R.id.favimage);
|
||||
|
||||
mReloadButton = (ImageButton) findViewById(R.id.reload);
|
||||
mReloadButton.setOnClickListener(new ImageButton.OnClickListener() {
|
||||
mTabs = (Button) findViewById(R.id.tabs);
|
||||
mTabs.setText("1");
|
||||
mTabs.setOnClickListener(new Button.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
onReload();
|
||||
showTabs();
|
||||
}
|
||||
});
|
||||
|
||||
mFavicon = (ImageButton) findViewById(R.id.favimage);
|
||||
}
|
||||
|
||||
private void onAwesomeBarSearch() {
|
||||
GeckoApp.mAppContext.onSearchRequested();
|
||||
}
|
||||
|
||||
private void onReload() {
|
||||
GeckoApp.mAppContext.doReload();
|
||||
private void showTabs() {
|
||||
GeckoApp.mAppContext.showTabs();
|
||||
}
|
||||
|
||||
public void updateTabs(int count) {
|
||||
mTabs.setText("" + count);
|
||||
}
|
||||
|
||||
public void updateProgress(int progress, int total) {
|
||||
|
@ -22,6 +22,7 @@
|
||||
* Vladimir Vukicevic <vladimir@pobox.com>
|
||||
* Matt Brubeck <mbrubeck@mozilla.com>
|
||||
* Vivien Nicolas <vnicolas@mozilla.com>
|
||||
* Sriram Ramasubramanian <sriram@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -49,6 +50,8 @@ import java.nio.channels.FileChannel;
|
||||
import java.util.concurrent.*;
|
||||
import java.lang.reflect.*;
|
||||
|
||||
import org.json.*;
|
||||
|
||||
import android.os.*;
|
||||
import android.app.*;
|
||||
import android.text.*;
|
||||
@ -58,6 +61,7 @@ import android.content.*;
|
||||
import android.content.res.*;
|
||||
import android.graphics.*;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.widget.*;
|
||||
import android.hardware.*;
|
||||
|
||||
@ -72,7 +76,7 @@ import android.content.SharedPreferences.*;
|
||||
import dalvik.system.*;
|
||||
|
||||
abstract public class GeckoApp
|
||||
extends Activity
|
||||
extends Activity implements GeckoEventListener
|
||||
{
|
||||
private static final String LOG_FILE_NAME = "GeckoApp";
|
||||
|
||||
@ -93,6 +97,9 @@ abstract public class GeckoApp
|
||||
private IntentFilter mConnectivityFilter;
|
||||
private BroadcastReceiver mConnectivityReceiver;
|
||||
private BrowserToolbar mBrowserToolbar;
|
||||
private PopupWindow mTabsTray;
|
||||
private TabsAdapter mTabsAdapter;
|
||||
private static boolean isTabsTrayShowing;
|
||||
|
||||
enum LaunchState {Launching, WaitButton,
|
||||
Launched, GeckoRunning, GeckoExiting};
|
||||
@ -102,7 +109,6 @@ abstract public class GeckoApp
|
||||
private static final int FILE_PICKER_REQUEST = 1;
|
||||
private static final int AWESOMEBAR_REQUEST = 2;
|
||||
private static final int CAMERA_CAPTURE_REQUEST = 3;
|
||||
private static final int SHOW_TABS_REQUEST = 4;
|
||||
|
||||
static boolean checkLaunchState(LaunchState checkState) {
|
||||
synchronized(sLaunchState) {
|
||||
@ -296,7 +302,7 @@ abstract public class GeckoApp
|
||||
boolean launch(Intent intent)
|
||||
{
|
||||
Log.w(LOGTAG, "zerdatime " + new Date().getTime() + " - launch");
|
||||
|
||||
|
||||
if (!checkAndSetLaunchState(LaunchState.Launching, LaunchState.Launched))
|
||||
return false;
|
||||
|
||||
@ -408,10 +414,8 @@ abstract public class GeckoApp
|
||||
Intent.ACTION_SEND, he.mTitle);
|
||||
}
|
||||
return true;
|
||||
case R.id.show_tabs:
|
||||
Intent showTabsIntent = new Intent(this, ShowTabs.class);
|
||||
showTabsIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_NO_HISTORY);
|
||||
startActivityForResult(showTabsIntent, SHOW_TABS_REQUEST);
|
||||
case R.id.reload:
|
||||
doReload();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
@ -477,6 +481,177 @@ abstract public class GeckoApp
|
||||
});
|
||||
}
|
||||
|
||||
void showTabs() {
|
||||
DisplayMetrics metrics = new DisplayMetrics();
|
||||
getWindowManager().getDefaultDisplay().getMetrics(metrics);
|
||||
|
||||
int width = metrics.widthPixels;
|
||||
int height = (int) (metrics.widthPixels * 0.75);
|
||||
LayoutInflater inflater = (LayoutInflater) mAppContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
mTabsTray = new PopupWindow(inflater.inflate(R.layout.tabs_tray, null, false),
|
||||
width,
|
||||
height,
|
||||
true);
|
||||
mTabsTray.setBackgroundDrawable(new BitmapDrawable());
|
||||
mTabsTray.setOutsideTouchable(true);
|
||||
|
||||
ListView list = (ListView) mTabsTray.getContentView().findViewById(R.id.list);
|
||||
Button addTab = new Button(this);
|
||||
addTab.setText(R.string.new_tab);
|
||||
addTab.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
hideTabs();
|
||||
Intent intent = new Intent(mAppContext, AwesomeBar.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_NO_HISTORY);
|
||||
intent.putExtra(AwesomeBar.TYPE_KEY, AwesomeBar.Type.ADD.name());
|
||||
startActivityForResult(intent, AWESOMEBAR_REQUEST);
|
||||
}
|
||||
});
|
||||
|
||||
list.addFooterView(addTab);
|
||||
isTabsTrayShowing = true;
|
||||
onTabsChanged();
|
||||
mTabsTray.showAsDropDown(mBrowserToolbar.findViewById(R.id.tabs));
|
||||
}
|
||||
|
||||
void hideTabs() {
|
||||
if (mTabsTray.isShowing()) {
|
||||
mTabsAdapter = null;
|
||||
((ListView) mTabsTray.getContentView().findViewById(R.id.list)).invalidateViews();
|
||||
mTabsTray.dismiss();
|
||||
isTabsTrayShowing = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void onTabsChanged() {
|
||||
if (mTabsTray == null)
|
||||
return;
|
||||
|
||||
if (!isTabsTrayShowing)
|
||||
return;
|
||||
|
||||
final HashMap<Integer, Tab> tabs = Tabs.getInstance().getTabs();
|
||||
if (mTabsAdapter != null) {
|
||||
mTabsAdapter = new TabsAdapter(mAppContext, tabs);
|
||||
mTabsAdapter.notifyDataSetChanged();
|
||||
ListView list = (ListView) mTabsTray.getContentView().findViewById(R.id.list);
|
||||
list.invalidateViews();
|
||||
list.setAdapter(mTabsAdapter);
|
||||
} else {
|
||||
mTabsAdapter = new TabsAdapter(mAppContext, tabs);
|
||||
ListView list = (ListView) mTabsTray.getContentView().findViewById(R.id.list);
|
||||
list.setAdapter(mTabsAdapter);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleMessage(String event, JSONObject message) {
|
||||
try {
|
||||
if (event.equals("DOMContentLoaded")) {
|
||||
final int tabId = message.getInt("tabID");
|
||||
final String uri = message.getString("uri");
|
||||
final String title = message.getString("title");
|
||||
final CharSequence titleText = title;
|
||||
handleContentLoaded(tabId, uri, title);
|
||||
Log.i("GeckoShell", "URI - " + uri + ", title - " + title);
|
||||
} else if (event.equals("DOMTitleChanged")) {
|
||||
final int tabId = message.getInt("tabID");
|
||||
final String title = message.getString("title");
|
||||
final CharSequence titleText = title;
|
||||
handleTitleChanged(tabId, title);
|
||||
Log.i("GeckoShell", "title - " + title);
|
||||
} else if (event.equals("DOMLinkAdded")) {
|
||||
final int tabId = message.getInt("tabID");
|
||||
final String rel = message.getString("rel");
|
||||
final String href = message.getString("href");
|
||||
Log.i("GeckoShell", "link rel - " + rel + ", href - " + href);
|
||||
handleLinkAdded(tabId, rel, href);
|
||||
} else if (event.equals("log")) {
|
||||
// generic log listener
|
||||
final String msg = message.getString("msg");
|
||||
Log.i("GeckoShell", "Log: " + msg);
|
||||
} else if (event.equals("onLocationChange")) {
|
||||
final int tabId = message.getInt("tabID");
|
||||
final String uri = message.getString("uri");
|
||||
Log.i("GeckoShell", "URI - " + uri);
|
||||
handleLocationChange(tabId, uri);
|
||||
} else if (event.equals("onStateChange")) {
|
||||
final int tabId = message.getInt("tabID");
|
||||
int state = message.getInt("state");
|
||||
Log.i("GeckoShell", "State - " + state);
|
||||
if ((state & GeckoAppShell.WPL_STATE_IS_DOCUMENT) != 0) {
|
||||
if ((state & GeckoAppShell.WPL_STATE_START) != 0) {
|
||||
Log.i("GeckoShell", "Got a document start");
|
||||
handleDocumentStart(tabId);
|
||||
} else if ((state & GeckoAppShell.WPL_STATE_STOP) != 0) {
|
||||
Log.i("GeckoShell", "Got a document stop");
|
||||
handleDocumentStop(tabId);
|
||||
}
|
||||
}
|
||||
} else if (event.equals("onProgressChange")) {
|
||||
final int tabId = message.getInt("tabID");
|
||||
final int current = message.getInt("current");
|
||||
final int total = message.getInt("total");
|
||||
|
||||
handleProgressChange(tabId, current, total);
|
||||
Log.i("GeckoShell", "progress - " + current + "/" + total);
|
||||
} else if (event.equals("onCameraCapture")) {
|
||||
//GeckoApp.mAppContext.doCameraCapture(message.getString("path"));
|
||||
doCameraCapture();
|
||||
} else if (event.equals("Tab:Added")) {
|
||||
Log.i("GeckoShell", "Created a new tab");
|
||||
int tabId = message.getInt("tabID");
|
||||
String uri = message.getString("uri");
|
||||
handleAddTab(tabId, uri);
|
||||
} else if (event.equals("Tab:Closed")) {
|
||||
Log.i("GeckoShell", "Destroyed a tab");
|
||||
int tabId = message.getInt("tabID");
|
||||
handleCloseTab(tabId);
|
||||
} else if (event.equals("Tab:Selected")) {
|
||||
int tabId = message.getInt("tabID");
|
||||
Log.i("GeckoShell", "Switched to tab: " + tabId);
|
||||
handleSelectTab(tabId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.i("GeckoApp", "handleMessage throws " + e + " for message: " + event);
|
||||
}
|
||||
}
|
||||
|
||||
void handleAddTab(final int tabId, final String uri) {
|
||||
Tab tab = Tabs.getInstance().addTab(tabId, uri);
|
||||
tab.updateFavicon(mAppContext.getResources().getDrawable(R.drawable.favicon));
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
onTabsChanged();
|
||||
mBrowserToolbar.updateTabs(Tabs.getInstance().getCount());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void handleCloseTab(final int tabId) {
|
||||
Tabs.getInstance().removeTab(tabId);
|
||||
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
onTabsChanged();
|
||||
mBrowserToolbar.updateTabs(Tabs.getInstance().getCount());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void handleSelectTab(final int tabId) {
|
||||
final Tab tab = Tabs.getInstance().selectTab(tabId);
|
||||
if (tab == null)
|
||||
return;
|
||||
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
mBrowserToolbar.setTitle(tab.getTitle());
|
||||
mBrowserToolbar.setFavicon(tab.getFavicon());
|
||||
mBrowserToolbar.setProgressVisibility(tab.isLoading());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void handleDocumentStart(final int tabId) {
|
||||
Tab tab = Tabs.getInstance().getTab(tabId);
|
||||
|
||||
@ -485,6 +660,12 @@ abstract public class GeckoApp
|
||||
|
||||
tab.setLoading(true);
|
||||
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
onTabsChanged();
|
||||
}
|
||||
});
|
||||
|
||||
if (!Tabs.getInstance().isSelectedTab(tab))
|
||||
return;
|
||||
|
||||
@ -498,7 +679,17 @@ abstract public class GeckoApp
|
||||
|
||||
void handleDocumentStop(final int tabId) {
|
||||
Tab tab = Tabs.getInstance().getTab(tabId);
|
||||
tab.setLoading(false);
|
||||
|
||||
if (tab == null)
|
||||
return;
|
||||
|
||||
tab.setLoading(false);
|
||||
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
onTabsChanged();
|
||||
}
|
||||
});
|
||||
|
||||
if (!Tabs.getInstance().isSelectedTab(tab))
|
||||
return;
|
||||
@ -513,6 +704,9 @@ abstract public class GeckoApp
|
||||
|
||||
void handleProgressChange(final int tabId, final int current, final int total) {
|
||||
Tab tab = Tabs.getInstance().getTab(tabId);
|
||||
if (tab == null)
|
||||
return;
|
||||
|
||||
if (!Tabs.getInstance().isSelectedTab(tab))
|
||||
return;
|
||||
|
||||
@ -525,9 +719,18 @@ abstract public class GeckoApp
|
||||
|
||||
void handleContentLoaded(final int tabId, final String uri, final String title) {
|
||||
Tab tab = Tabs.getInstance().getTab(tabId);
|
||||
if (tab == null)
|
||||
return;
|
||||
|
||||
tab.updateTitle(title);
|
||||
tab.addHistory(new Tab.HistoryEntry(uri, title));
|
||||
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
onTabsChanged();
|
||||
}
|
||||
});
|
||||
|
||||
if (!Tabs.getInstance().isSelectedTab(tab))
|
||||
return;
|
||||
|
||||
@ -540,6 +743,9 @@ abstract public class GeckoApp
|
||||
|
||||
void handleTitleChanged(final int tabId, final String title) {
|
||||
Tab tab = Tabs.getInstance().getTab(tabId);
|
||||
if (tab == null)
|
||||
return;
|
||||
|
||||
tab.updateTitle(title);
|
||||
|
||||
if (!Tabs.getInstance().isSelectedTab(tab))
|
||||
@ -547,12 +753,13 @@ abstract public class GeckoApp
|
||||
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
onTabsChanged();
|
||||
mBrowserToolbar.setTitle(title);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void handleLinkAdded(String rel, final String href) {
|
||||
void handleLinkAdded(final int tabId, String rel, final String href) {
|
||||
class DownloadFaviconTask extends AsyncTask<URL, Void, Drawable> {
|
||||
protected Drawable doInBackground(URL... url) {
|
||||
Drawable image = null;
|
||||
@ -566,6 +773,21 @@ abstract public class GeckoApp
|
||||
}
|
||||
protected void onPostExecute(Drawable image) {
|
||||
if (image != null) {
|
||||
Tab tab = Tabs.getInstance().getTab(tabId);
|
||||
if (tab == null)
|
||||
return;
|
||||
|
||||
tab.updateFavicon(image);
|
||||
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
onTabsChanged();
|
||||
}
|
||||
});
|
||||
|
||||
if (!Tabs.getInstance().isSelectedTab(tab))
|
||||
return;
|
||||
|
||||
final Drawable postImage = image;
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
@ -585,7 +807,7 @@ abstract public class GeckoApp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void addPluginView(final View view,
|
||||
final double x, final double y,
|
||||
final double w, final double h) {
|
||||
@ -699,6 +921,20 @@ abstract public class GeckoApp
|
||||
|
||||
mMainLayout = (LinearLayout) findViewById(R.id.mainLayout);
|
||||
mBrowserToolbar = (BrowserToolbar) findViewById(R.id.browserToolbar);
|
||||
|
||||
//register for events
|
||||
GeckoAppShell.registerGeckoEventListener("DOMContentLoaded", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("DOMTitleChanged", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("DOMLinkAdded", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("log", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("onLocationChange", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("onStateChange", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("onProgressChange", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("onCameraCapture", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("Tab:Added", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("Tab:Closed", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("Tab:Selected", GeckoApp.mAppContext);
|
||||
|
||||
|
||||
mConnectivityFilter = new IntentFilter();
|
||||
mConnectivityFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||
@ -874,6 +1110,23 @@ abstract public class GeckoApp
|
||||
GeckoAppShell.getPromptService().onDestroy();
|
||||
}
|
||||
});
|
||||
|
||||
if (mTabsTray != null && mTabsTray.isShowing()) {
|
||||
hideTabs();
|
||||
mTabsTray = null;
|
||||
}
|
||||
|
||||
GeckoAppShell.unregisterGeckoEventListener("DOMContentLoaded", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("DOMTitleChanged", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("DOMLinkAdded", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("log", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("onLocationChange", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("onStateChange", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("onProgressChange", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("onCameraCapture", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("Tab:Added", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("Tab:Closed", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("Tab:Selected", GeckoApp.mAppContext);
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
@ -1145,24 +1398,6 @@ abstract public class GeckoApp
|
||||
"{\"ok\": false, \"path\": \"" + file.getPath() + "\" }");
|
||||
GeckoAppShell.sendEventToGecko(e);
|
||||
break;
|
||||
case SHOW_TABS_REQUEST:
|
||||
if (data != null) {
|
||||
ShowTabs.Type type = ShowTabs.Type.valueOf(data.getStringExtra(ShowTabs.TYPE));
|
||||
if (type == ShowTabs.Type.ADD) {
|
||||
Intent intent = new Intent(this, AwesomeBar.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_NO_HISTORY);
|
||||
intent.putExtra(AwesomeBar.TYPE_KEY, AwesomeBar.Type.ADD.name());
|
||||
startActivityForResult(intent, AWESOMEBAR_REQUEST);
|
||||
} else {
|
||||
int id = Integer.parseInt(data.getStringExtra(ShowTabs.ID));
|
||||
Tab tab = Tabs.getInstance().selectTab(id);
|
||||
if (tab != null) {
|
||||
mBrowserToolbar.setTitle(tab.getTitle());
|
||||
mBrowserToolbar.setProgressVisibility(tab.isLoading());
|
||||
}
|
||||
GeckoAppShell.sendEventToGecko(new GeckoEvent("tab-select", "" + id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1179,9 +1414,109 @@ abstract public class GeckoApp
|
||||
mBrowserToolbar.setTitle(url);
|
||||
Log.d(LOG_FILE_NAME, type.name());
|
||||
if (type == AwesomeBar.Type.ADD) {
|
||||
GeckoAppShell.sendEventToGecko(new GeckoEvent("tab-add", url));
|
||||
GeckoAppShell.sendEventToGecko(new GeckoEvent("Tab:Add", url));
|
||||
} else {
|
||||
GeckoAppShell.sendEventToGecko(new GeckoEvent("tab-load", url));
|
||||
GeckoAppShell.sendEventToGecko(new GeckoEvent("Tab:Load", url));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adapter to bind tabs into a list
|
||||
private class TabsAdapter extends BaseAdapter {
|
||||
public TabsAdapter(Context context, HashMap<Integer, Tab> tabs) {
|
||||
mContext = context;
|
||||
mTabs = new ArrayList<Tab>();
|
||||
|
||||
if (tabs != null) {
|
||||
Iterator keys = tabs.keySet().iterator();
|
||||
Tab tab;
|
||||
while (keys.hasNext()) {
|
||||
tab = tabs.get(keys.next());
|
||||
mTabs.add(tab);
|
||||
}
|
||||
}
|
||||
|
||||
mInflater = LayoutInflater.from(mContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mTabs.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tab getItem(int position) {
|
||||
return mTabs.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
|
||||
if (convertView == null)
|
||||
convertView = mInflater.inflate(R.layout.tabs_row, null);
|
||||
|
||||
Tab tab = mTabs.get(position);
|
||||
|
||||
LinearLayout info = (LinearLayout) convertView.findViewById(R.id.info);
|
||||
info.setTag("" + tab.getId());
|
||||
info.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
hideTabs();
|
||||
GeckoAppShell.sendEventToGecko(new GeckoEvent("Tab:Select", "" + v.getTag()));
|
||||
}
|
||||
});
|
||||
|
||||
ImageView favicon = (ImageView) convertView.findViewById(R.id.favicon);
|
||||
favicon.setImageDrawable(tab.getFavicon());
|
||||
|
||||
TextView title = (TextView) convertView.findViewById(R.id.title);
|
||||
title.setText(tab.getTitle());
|
||||
|
||||
TextView url = (TextView) convertView.findViewById(R.id.url);
|
||||
url.setText(tab.getURL());
|
||||
|
||||
ImageButton close = (ImageButton) convertView.findViewById(R.id.close);
|
||||
if (mTabs.size() > 1) {
|
||||
close.setTag("" + tab.getId());
|
||||
close.setOnClickListener(new Button.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
int tabId = Integer.parseInt("" + v.getTag());
|
||||
Tabs tabs = Tabs.getInstance();
|
||||
Tab tab = tabs.getTab(tabId);
|
||||
|
||||
if (tabs.isSelectedTab(tab)) {
|
||||
int index = tabs.getIndexOf(tab);
|
||||
if (index >= 1)
|
||||
index--;
|
||||
else
|
||||
index = 1;
|
||||
int id = tabs.getTabAt(index).getId();
|
||||
GeckoAppShell.sendEventToGecko(new GeckoEvent("Tab:Select", "" + id));
|
||||
GeckoAppShell.sendEventToGecko(new GeckoEvent("Tab:Close", "" + v.getTag()));
|
||||
} else {
|
||||
GeckoAppShell.sendEventToGecko(new GeckoEvent("Tab:Close", "" + v.getTag()));
|
||||
GeckoAppShell.sendEventToGecko(new GeckoEvent("Tab:Select", "" + tabs.getSelectedTabId()));
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
close.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyDataSetChanged() {
|
||||
}
|
||||
|
||||
|
||||
private Context mContext;
|
||||
private ArrayList<Tab> mTabs;
|
||||
private LayoutInflater mInflater;
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
* Vladimir Vukicevic <vladimir@pobox.com>
|
||||
* Sriram Ramasubramanian <sriram@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -99,13 +100,15 @@ public class GeckoAppShell
|
||||
/* Keep in sync with constants found here:
|
||||
http://mxr.mozilla.org/mozilla-central/source/uriloader/base/nsIWebProgressListener.idl
|
||||
*/
|
||||
static private final int WPL_STATE_START = 0x00000001;
|
||||
static private final int WPL_STATE_STOP = 0x00000010;
|
||||
static private final int WPL_STATE_IS_DOCUMENT = 0x00020000;
|
||||
static public final int WPL_STATE_START = 0x00000001;
|
||||
static public final int WPL_STATE_STOP = 0x00000010;
|
||||
static public final int WPL_STATE_IS_DOCUMENT = 0x00020000;
|
||||
|
||||
static private File sCacheFile = null;
|
||||
static private int sFreeSpace = -1;
|
||||
|
||||
private static HashMap<String, ArrayList<GeckoEventListener>> mEventListeners;
|
||||
|
||||
/* The Android-side API: API methods that Android calls */
|
||||
|
||||
// Initialization methods
|
||||
@ -1502,6 +1505,28 @@ public class GeckoAppShell
|
||||
|
||||
static SynchronousQueue<String> sPromptQueue = null;
|
||||
|
||||
public static void registerGeckoEventListener(String event, GeckoEventListener listener) {
|
||||
if (mEventListeners == null)
|
||||
mEventListeners = new HashMap<String, ArrayList<GeckoEventListener>>();
|
||||
|
||||
if (!mEventListeners.containsKey(event))
|
||||
mEventListeners.put(event, new ArrayList<GeckoEventListener>());
|
||||
|
||||
ArrayList<GeckoEventListener> listeners = mEventListeners.get(event);
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public static void unregisterGeckoEventListener(String event, GeckoEventListener listener) {
|
||||
if (mEventListeners == null)
|
||||
return;
|
||||
|
||||
if (!mEventListeners.containsKey(event))
|
||||
return;
|
||||
|
||||
ArrayList<GeckoEventListener> listeners = mEventListeners.get(event);
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
public static String handleGeckoMessage(String message) {
|
||||
//
|
||||
// {"gecko": {
|
||||
@ -1512,63 +1537,8 @@ public class GeckoAppShell
|
||||
JSONObject json = new JSONObject(message);
|
||||
final JSONObject geckoObject = json.getJSONObject("gecko");
|
||||
String type = geckoObject.getString("type");
|
||||
|
||||
if (type.equals("DOMContentLoaded")) {
|
||||
final int tabId = geckoObject.getInt("tabID");
|
||||
final String uri = geckoObject.getString("uri");
|
||||
final String title = geckoObject.getString("title");
|
||||
final CharSequence titleText = title;
|
||||
GeckoApp.mAppContext.handleContentLoaded(tabId, uri, title);
|
||||
Log.i("GeckoShell", "URI - " + uri + ", title - " + title);
|
||||
} else if (type.equals("DOMTitleChanged")) {
|
||||
final int tabId = geckoObject.getInt("tabID");
|
||||
final String title = geckoObject.getString("title");
|
||||
final CharSequence titleText = title;
|
||||
GeckoApp.mAppContext.handleTitleChanged(tabId, title);
|
||||
Log.i("GeckoShell", "title - " + title);
|
||||
} else if (type.equals("DOMLinkAdded")) {
|
||||
final String rel = geckoObject.getString("rel");
|
||||
final String href = geckoObject.getString("href");
|
||||
Log.i("GeckoShell", "link rel - " + rel + ", href - " + href);
|
||||
GeckoApp.mAppContext.handleLinkAdded(rel, href);
|
||||
} else if (type.equals("log")) {
|
||||
// generic log listener
|
||||
final String msg = geckoObject.getString("msg");
|
||||
Log.i("GeckoShell", "Log: " + msg);
|
||||
} else if (type.equals("onLocationChange")) {
|
||||
final int tabId = geckoObject.getInt("tabID");
|
||||
final String uri = geckoObject.getString("uri");
|
||||
Log.i("GeckoShell", "URI - " + uri);
|
||||
GeckoApp.mAppContext.handleLocationChange(tabId, uri);
|
||||
} else if (type.equals("onStateChange")) {
|
||||
final int tabId = geckoObject.getInt("tabID");
|
||||
int state = geckoObject.getInt("state");
|
||||
Log.i("GeckoShell", "State - " + state);
|
||||
if ((state & WPL_STATE_IS_DOCUMENT) != 0) {
|
||||
if ((state & WPL_STATE_START) != 0) {
|
||||
Log.i("GeckoShell", "Got a document start");
|
||||
GeckoApp.mAppContext.handleDocumentStart(tabId);
|
||||
} else if ((state & WPL_STATE_STOP) != 0) {
|
||||
Log.i("GeckoShell", "Got a document stop");
|
||||
GeckoApp.mAppContext.handleDocumentStop(tabId);
|
||||
}
|
||||
}
|
||||
} else if (type.equals("onProgressChange")) {
|
||||
final int tabId = geckoObject.getInt("tabID");
|
||||
final int current = geckoObject.getInt("current");
|
||||
final int total = geckoObject.getInt("total");
|
||||
|
||||
GeckoApp.mAppContext.handleProgressChange(tabId, current, total);
|
||||
Log.i("GeckoShell", "progress - " + current + "/" + total);
|
||||
} else if (type.equals("onCameraCapture")) {
|
||||
//GeckoApp.mAppContext.doCameraCapture(geckoObject.getString("path"));
|
||||
GeckoApp.mAppContext.doCameraCapture();
|
||||
} else if (type.equals("onCreateTab")) {
|
||||
Log.i("GeckoShell", "Created a new tab");
|
||||
int tabId = geckoObject.getInt("tabID");
|
||||
String uri = geckoObject.getString("uri");
|
||||
Tabs.getInstance().addTab(tabId, uri);
|
||||
} else if (type.equals("prompt")) {
|
||||
|
||||
if (type.equals("prompt")) {
|
||||
if (sPromptQueue == null)
|
||||
sPromptQueue = new SynchronousQueue<String>();
|
||||
getHandler().post(new Runnable() {
|
||||
@ -1586,9 +1556,23 @@ public class GeckoAppShell
|
||||
}
|
||||
return promptServiceResult;
|
||||
}
|
||||
|
||||
if (mEventListeners == null)
|
||||
return "";
|
||||
|
||||
if (!mEventListeners.containsKey(type))
|
||||
return "";
|
||||
|
||||
ArrayList<GeckoEventListener> listeners = mEventListeners.get(type);
|
||||
Iterator items = listeners.iterator();
|
||||
while (items.hasNext()) {
|
||||
((GeckoEventListener) items.next()).handleMessage(type, geckoObject);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.i("GeckoShell", "handleGeckoMessage throws " + e);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
44
embedding/android/GeckoEventListener.java
Normal file
44
embedding/android/GeckoEventListener.java
Normal file
@ -0,0 +1,44 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Android code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009-2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sriram Ramasubramanian <sriram@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
public interface GeckoEventListener {
|
||||
public void handleMessage(String event, JSONObject message);
|
||||
}
|
@ -58,7 +58,7 @@ JAVAFILES = \
|
||||
GeckoBookmarks.java \
|
||||
Tab.java \
|
||||
Tabs.java \
|
||||
ShowTabs.java \
|
||||
GeckoEventListener.java \
|
||||
PromptService.java \
|
||||
SurfaceInfo.java \
|
||||
$(NULL)
|
||||
@ -139,7 +139,8 @@ RES_LAYOUT = \
|
||||
res/layout/browser_toolbar.xml \
|
||||
res/layout/bookmarks.xml \
|
||||
res/layout/bookmark_list_row.xml \
|
||||
res/layout/show_tabs.xml \
|
||||
res/layout/tabs_tray.xml \
|
||||
res/layout/tabs_row.xml \
|
||||
res/layout/dialog_checkbox.xml \
|
||||
$(NULL)
|
||||
|
||||
|
@ -1,121 +0,0 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Android code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sriram Ramasubramanian <sriram@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import org.mozilla.gecko.*;
|
||||
|
||||
import android.os.*;
|
||||
import android.content.*;
|
||||
import android.app.*;
|
||||
import android.text.*;
|
||||
import android.util.*;
|
||||
import android.widget.*;
|
||||
import android.database.sqlite.*;
|
||||
import android.database.*;
|
||||
import android.view.*;
|
||||
import android.view.View.*;
|
||||
import android.net.Uri;
|
||||
import android.graphics.*;
|
||||
|
||||
public class ShowTabs extends ListActivity {
|
||||
private static final String LOG_FILE_NAME = "ShowTabs";
|
||||
public static final String ID = "id";
|
||||
public static final String TYPE = "type";
|
||||
private ArrayList <HashMap<String, String>> tabsList = null;
|
||||
public static enum Type { ADD, SWITCH };
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
setContentView(R.layout.show_tabs);
|
||||
|
||||
ListView list = (ListView) findViewById(android.R.id.list);
|
||||
Button addTab = new Button(this);
|
||||
addTab.setText("+ add tab");
|
||||
addTab.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
Intent resultIntent = new Intent();
|
||||
resultIntent.putExtra(TYPE, Type.ADD.name());
|
||||
setResult(Activity.RESULT_OK, resultIntent);
|
||||
finish();
|
||||
}
|
||||
});
|
||||
|
||||
list.addHeaderView(addTab);
|
||||
|
||||
HashMap<Integer, Tab> tabs = Tabs.getInstance().getTabs();
|
||||
tabsList = new ArrayList<HashMap<String, String>> ();
|
||||
|
||||
if (tabs != null) {
|
||||
Iterator keys = tabs.keySet().iterator();
|
||||
HashMap<String, String> map;
|
||||
Tab tab;
|
||||
while (keys.hasNext()) {
|
||||
tab = tabs.get(keys.next());
|
||||
map = new HashMap<String, String>();
|
||||
map.put("id", "" + tab.getId());
|
||||
map.put("title", tab.getTitle());
|
||||
map.put("url", tab.getURL());
|
||||
tabsList.add(map);
|
||||
}
|
||||
}
|
||||
|
||||
list.setAdapter(new SimpleAdapter(
|
||||
ShowTabs.this,
|
||||
tabsList,
|
||||
R.layout.awesomebar_row,
|
||||
new String[] { "title", "url" },
|
||||
new int[] { R.id.title, R.id.url }
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListItemClick(ListView l, View v, int position, long id) {
|
||||
HashMap<String, String> map = tabsList.get((int) id);
|
||||
Intent resultIntent = new Intent();
|
||||
resultIntent.putExtra(TYPE, Type.SWITCH.name());
|
||||
resultIntent.putExtra(ID, map.get("id"));
|
||||
setResult(Activity.RESULT_OK, resultIntent);
|
||||
finish();
|
||||
}
|
||||
}
|
@ -95,6 +95,10 @@ public class Tab {
|
||||
return title;
|
||||
}
|
||||
|
||||
public Drawable getFavicon() {
|
||||
return favicon;
|
||||
}
|
||||
|
||||
public boolean isLoading() {
|
||||
return loading;
|
||||
}
|
||||
|
@ -47,9 +47,11 @@ public class Tabs {
|
||||
private static final String LOG_FILE_NAME = "Tabs";
|
||||
private static int selectedTab = -1;
|
||||
private HashMap<Integer, Tab> tabs;
|
||||
private ArrayList<Tab> order;
|
||||
|
||||
private Tabs() {
|
||||
tabs = new HashMap<Integer, Tab>();
|
||||
order = new ArrayList<Tab>();
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
@ -62,6 +64,7 @@ public class Tabs {
|
||||
|
||||
Tab tab = new Tab(id, url);
|
||||
tabs.put(id, tab);
|
||||
order.add(tab);
|
||||
Log.i(LOG_FILE_NAME, "Added a tab with id: " + id + ", url: " + url);
|
||||
selectedTab = id;
|
||||
return tab;
|
||||
@ -69,6 +72,7 @@ public class Tabs {
|
||||
|
||||
public void removeTab(int id) {
|
||||
if (tabs.containsKey(id)) {
|
||||
order.remove(getTab(id));
|
||||
tabs.remove(id);
|
||||
Log.i(LOG_FILE_NAME, "Removed a tab with id: " + id);
|
||||
}
|
||||
@ -82,6 +86,17 @@ public class Tabs {
|
||||
return tabs.get(id);
|
||||
}
|
||||
|
||||
public int getIndexOf(Tab tab) {
|
||||
return order.lastIndexOf(tab);
|
||||
}
|
||||
|
||||
public Tab getTabAt(int index) {
|
||||
if (index < order.size())
|
||||
return order.get(index);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public Tab getSelectedTab() {
|
||||
return tabs.get(selectedTab);
|
||||
}
|
||||
|
@ -23,7 +23,9 @@
|
||||
<!ENTITY bookmarks "Bookmarks">
|
||||
<!ENTITY bookmark_add "Add Bookmark">
|
||||
|
||||
<!ENTITY tabs "Tabs">
|
||||
<!ENTITY reload "Reload">
|
||||
|
||||
<!ENTITY new_tab "New Tab">
|
||||
|
||||
<!ENTITY quit "Quit">
|
||||
|
||||
|
@ -9,19 +9,18 @@
|
||||
|
||||
<LinearLayout android:id="@+id/address_bar"
|
||||
style="@style/AddressBar">
|
||||
|
||||
<Button android:id="@+id/tabs"
|
||||
style="@style/AddressBar.Button.Left"/>
|
||||
|
||||
<ImageButton android:id="@+id/favimage"
|
||||
style="@style/AddressBar.ImageButton.Left"
|
||||
style="@style/AddressBar.ImageButton.Middle"
|
||||
android:src="@drawable/favicon"/>
|
||||
|
||||
<Button android:id="@+id/awesome_bar"
|
||||
style="@style/AddressBar.URL"
|
||||
android:textColor="#666"/>
|
||||
|
||||
<ImageButton android:id="@+id/reload"
|
||||
style="@style/AddressBar.ImageButton.Right"
|
||||
android:src="@drawable/reload"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</merge>
|
||||
|
@ -1,9 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:id="@+id/quit"
|
||||
android:icon="@drawable/quit"
|
||||
android:title="@string/quit" />
|
||||
<item android:id="@+id/reload"
|
||||
android:title="@string/reload"/>
|
||||
|
||||
<item android:id="@+id/bookmarks"
|
||||
android:title="@string/bookmarks"
|
||||
@ -13,8 +12,8 @@
|
||||
android:icon="@drawable/share"
|
||||
android:title="@string/share" />
|
||||
|
||||
<item android:id="@+id/show_tabs"
|
||||
android:title="@string/tabs"
|
||||
android:showAsAction="ifRoom"/>
|
||||
<item android:id="@+id/quit"
|
||||
android:icon="@drawable/quit"
|
||||
android:title="@string/quit" />
|
||||
|
||||
</menu>
|
||||
|
@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/awesomeScreen"
|
||||
style="@style/Screen">
|
||||
|
||||
<ListView android:id="@android:id/list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="#fff"
|
||||
android:cacheColorHint="#fff"
|
||||
android:divider="#666666"
|
||||
android:dividerHeight="1dp"/>
|
||||
|
||||
</LinearLayout>
|
54
embedding/android/resources/layout/tabs_row.xml
Normal file
54
embedding/android/resources/layout/tabs_row.xml
Normal file
@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#fefefe"
|
||||
android:padding="6dip"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout android:id="@+id/info"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1">
|
||||
|
||||
<ImageView android:id="@+id/favicon"
|
||||
android:layout_width="32dip"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginRight="6dip"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:scaleType="fitCenter"/>
|
||||
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginLeft="6dip"
|
||||
android:layout_marginRight="6dip"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceMediumInverse"
|
||||
android:textColor="#000"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="middle"/>
|
||||
|
||||
<TextView android:id="@+id/url"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceSmallInverse"
|
||||
android:textColor="?android:attr/textColorSecondaryInverse"
|
||||
android:layout_marginTop="2dip"
|
||||
android:includeFontPadding="false"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="middle"/>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<ImageButton android:id="@+id/close"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#00000000"
|
||||
android:src="@drawable/quit"/>
|
||||
|
||||
</LinearLayout>
|
9
embedding/android/resources/layout/tabs_tray.xml
Normal file
9
embedding/android/resources/layout/tabs_tray.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/address_bar_button_middle"
|
||||
android:cacheColorHint="#fff"
|
||||
android:divider="#666666"
|
||||
android:dividerHeight="1dp"/>
|
@ -45,23 +45,23 @@
|
||||
|
||||
<!-- Address bar - Button -->
|
||||
<style name="AddressBar.Button">
|
||||
<item name="android:layout_width">wrap_content</item>
|
||||
<item name="android:layout_width">40dip</item>
|
||||
<item name="android:layout_height">43dip</item>
|
||||
<item name="android:textSize">16sp</item>
|
||||
</style>
|
||||
|
||||
<!-- Address bar - Image Button -->
|
||||
<style name="AddressBar.ImageButton" parent="AddressBar.Button">
|
||||
<item name="android:scaleType">fitXY</item>
|
||||
<item name="android:layout_width">40dip</item>
|
||||
<item name="android:scaleType">fitCenter</item>
|
||||
</style>
|
||||
|
||||
<!-- Address bar - Left Button -->
|
||||
<style name="AddressBar.ImageButton.Left">
|
||||
<style name="AddressBar.Button.Left">
|
||||
<item name="android:background">@drawable/address_bar_button_left</item>
|
||||
</style>
|
||||
|
||||
<!-- Address bar - Right Button -->
|
||||
<style name="AddressBar.ImageButton.Right">
|
||||
<style name="AddressBar.Button.Right">
|
||||
<item name="android:background">@drawable/address_bar_button_right</item>
|
||||
</style>
|
||||
|
||||
@ -71,7 +71,8 @@
|
||||
</style>
|
||||
|
||||
<!-- Address bar - URL -->
|
||||
<style name="AddressBar.URL" parent="AddressBar.ImageButton.Middle">
|
||||
<style name="AddressBar.URL" parent="AddressBar.Button.Right">
|
||||
<item name="android:layout_width">wrap_content</item>
|
||||
<item name="android:orientation">horizontal</item>
|
||||
<item name="android:layout_weight">1</item>
|
||||
<item name="android:paddingLeft">10dip</item>
|
||||
|
@ -32,5 +32,6 @@
|
||||
|
||||
<string name="share">&share;</string>
|
||||
|
||||
<string name="tabs">&tabs;</string>
|
||||
<string name="reload">&reload;</string>
|
||||
<string name="new_tab">&new_tab;</string>
|
||||
</resources>
|
||||
|
@ -67,9 +67,10 @@ var BrowserApp = {
|
||||
this.deck = document.getElementById("browsers");
|
||||
BrowserEventHandler.init();
|
||||
|
||||
Services.obs.addObserver(this, "tab-add", false);
|
||||
Services.obs.addObserver(this, "tab-load", false);
|
||||
Services.obs.addObserver(this, "tab-select", false);
|
||||
Services.obs.addObserver(this, "Tab:Add", false);
|
||||
Services.obs.addObserver(this, "Tab:Load", false);
|
||||
Services.obs.addObserver(this, "Tab:Select", false);
|
||||
Services.obs.addObserver(this, "Tab:Close", false);
|
||||
Services.obs.addObserver(this, "session-back", false);
|
||||
Services.obs.addObserver(this, "session-reload", false);
|
||||
|
||||
@ -170,11 +171,18 @@ var BrowserApp = {
|
||||
this._tabs.splice(this._tabs.indexOf(aTab), 1);
|
||||
},
|
||||
|
||||
selectTab: function selectTab(aTabId) {
|
||||
let tab = this.getTabForId(aTabId);
|
||||
if (tab != null) {
|
||||
this.selectedTab = tab;
|
||||
tab.active = true;
|
||||
selectTab: function selectTab(aTab) {
|
||||
if (aTab != null) {
|
||||
this.selectedTab = aTab;
|
||||
aTab.active = true;
|
||||
let message = {
|
||||
gecko: {
|
||||
type: "Tab:Selected",
|
||||
tabID: aTab.id
|
||||
}
|
||||
};
|
||||
|
||||
sendMessageToJava(message);
|
||||
}
|
||||
},
|
||||
|
||||
@ -187,13 +195,15 @@ var BrowserApp = {
|
||||
browser.goBack();
|
||||
else if (aTopic == "session-reload")
|
||||
browser.reload();
|
||||
else if (aTopic == "tab-add") {
|
||||
else if (aTopic == "Tab:Add") {
|
||||
let newTab = this.addTab(aData);
|
||||
newTab.active = true;
|
||||
} else if (aTopic == "tab-load")
|
||||
} else if (aTopic == "Tab:Load")
|
||||
browser.loadURI(aData);
|
||||
else if (aTopic == "tab-select")
|
||||
this.selectTab(parseInt(aData));
|
||||
else if (aTopic == "Tab:Select")
|
||||
this.selectTab(this.getTabForId(parseInt(aData)));
|
||||
else if (aTopic == "Tab:Close")
|
||||
this.closeTab(this.getTabForId(parseInt(aData)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -254,7 +264,7 @@ Tab.prototype = {
|
||||
this.id = ++gTabIDFactory;
|
||||
let message = {
|
||||
gecko: {
|
||||
type: "onCreateTab",
|
||||
type: "Tab:Added",
|
||||
tabID: this.id,
|
||||
uri: aURL
|
||||
}
|
||||
@ -270,6 +280,14 @@ Tab.prototype = {
|
||||
this.browser.removeProgressListener(this);
|
||||
BrowserApp.deck.removeChild(this.browser);
|
||||
this.browser = null;
|
||||
let message = {
|
||||
gecko: {
|
||||
type: "Tab:Closed",
|
||||
tabID: this.id
|
||||
}
|
||||
};
|
||||
|
||||
sendMessageToJava(message);
|
||||
},
|
||||
|
||||
set active(aActive) {
|
||||
@ -394,8 +412,12 @@ var BrowserEventHandler = {
|
||||
if (!target.href || target.disabled)
|
||||
return;
|
||||
|
||||
let browser = BrowserApp.getBrowserForDocument(target.ownerDocument);
|
||||
let tabID = BrowserApp.getTabForBrowser(browser).id;
|
||||
|
||||
let json = {
|
||||
type: "DOMLinkAdded",
|
||||
tabID: tabID,
|
||||
windowId: target.ownerDocument.defaultView.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID,
|
||||
href: resolveGeckoURI(target.href),
|
||||
charset: target.ownerDocument.characterSet,
|
||||
|
Loading…
Reference in New Issue
Block a user