A small patch for workspace.js
- From: Nageswara <whatisthis20 gmail com>
- To: gnome-shell-list gnome org
- Subject: A small patch for workspace.js
- Date: Sun, 8 Nov 2009 12:28:31 +0530
Hello folks,
I recently tried gnome-shell on my ubuntu system and liked the overlay design concept very much. While using the shell, I felt that it would be better to have window action menu appeared in overview mode also. (when user right clicks on a window). Later, this menu can be extend to support app specific menus.
So with this idea, I went ahead and opened source and tried changing it. I'm attaching the patch to this mail. This is not yet completed, just looking for your suggestions. I couldn't find mutter api to get current state of window i.e. is_maximized/is_minimized etc., to hide irrelevant options (we shouldn't show maximize option when the window is already maximized). similarly, there is no api function to keep window on all workspaces :( If you ppl know alternative way of doing these things, please let me know.
Similary I've another idea too. When user maximizes a window, how about merging titlebar of the window with top-panel ? we are already showing window title in top-panel, why not buttons (I mean minimize, maximize buttons). That way we can save some screen real estate. For this we may need to work with mutter folks, not sure.
--
Naagas.
0__
_> /__...
(_) \(_) Burn fat, not fuel
diff --git a/js/ui/workspaces.js b/js/ui/workspaces.js
index 1cde8ac..a985c7d 100644
--- a/js/ui/workspaces.js
+++ b/js/ui/workspaces.js
@@ -10,6 +10,9 @@ const Meta = imports.gi.Meta;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
+const Gettext = imports.gettext.domain('gnome-shell');
+const _ = Gettext.gettext;
+
const DND = imports.ui.dnd;
const Lightbox = imports.ui.lightbox;
@@ -135,6 +138,13 @@ WindowClone.prototype = {
this._zooming = false;
},
+ updateClone: function() {
+ this.actor.set_source(this.realWindow.get_texture());
+ this.origX = this.realWindow.x;
+ this.origY = this.realWindow.y;
+ this.emit('clone-source-changed');
+ },
+
setVisibleWithChrome: function(visible) {
if (visible) {
this.actor.show();
@@ -268,7 +278,15 @@ WindowClone.prototype = {
},
_onButtonRelease : function (actor, event) {
- this.emit('selected', event.get_time());
+ let button = event.get_button();
+ if (button == 1) {
+ this.emit('selected', event.get_time());
+ } else if(button == 3) {
+ if (!this._menu) {
+ this._menu = new AppWindowMenu(this);
+ }
+ this._menu.popup(event.get_coords());
+ }
},
_onDragBegin : function (draggable, time) {
@@ -1258,7 +1276,10 @@ Workspace.prototype = {
Lang.bind(this, function() {
icon.show();
}));
-
+ clone.connect('clone-source-changed',
+ Lang.bind(this, function() {
+ this.positionWindows(false);
+ }));
this.actor.add_actor(clone.actor);
this._windows.push(clone);
@@ -1728,3 +1749,195 @@ function _workspaceRelativeGet(begin, end, time, params) {
// Return the workspace coordinates.
return (screen - curOverviewPos) / curOverviewScale - params.workspacePos;
}
+
+
+const APPWINDOW_DEFAULT_BORDER_COLOR = new Clutter.Color();
+APPWINDOW_DEFAULT_BORDER_COLOR.from_pixel(0x787878ff);
+const APPWINDOW_MENU_BACKGROUND_COLOR = new Clutter.Color();
+APPWINDOW_MENU_BACKGROUND_COLOR.from_pixel(0x292929ff);
+const APPWINDOW_MENU_FONT = 'Sans 14px';
+const APPWINDOW_MENU_COLOR = new Clutter.Color();
+APPWINDOW_MENU_COLOR.from_pixel(0xffffffff);
+const APPWINDOW_MENU_SELECTED_COLOR = new Clutter.Color();
+APPWINDOW_MENU_SELECTED_COLOR.from_pixel(0x005b97ff);
+const APPWINDOW_MENU_SEPARATOR_COLOR = new Clutter.Color();
+APPWINDOW_MENU_SEPARATOR_COLOR.from_pixel(0x787878ff);
+const APPWINDOW_MENU_BORDER_WIDTH = 1;
+const APPWINDOW_MENU_ARROW_SIZE = 12;
+const APPWINDOW_MENU_CORNER_RADIUS = 4;
+const APPWINDOW_MENU_PADDING = 4;
+
+const TRANSPARENT_COLOR = new Clutter.Color();
+TRANSPARENT_COLOR.from_pixel(0x00000000);
+
+const MenuType = { NONE: 0, ON_RIGHT: 1, BELOW: 2 };
+const MenuAction = { NONE: 0, CLOSE: 1, MAXIMIZE: 2, MINIMIZE: 3, UNMAXIMIZE: 4, UNMINIMIZE: 5, SHADE: 6, UNSHADE: 7 };
+
+
+function AppWindowMenu(source) {
+ this._init(source);
+}
+
+AppWindowMenu.prototype = {
+ _init: function(source) {
+ this._source = source;
+
+ this.actor = new Shell.GenericContainer({ reactive: true });
+ this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
+ this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
+ this.actor.connect('allocate', Lang.bind(this, this._allocate));
+
+ this._windowContainer = new Shell.Menu({ orientation: Big.BoxOrientation.VERTICAL,
+ border_color: APPWINDOW_DEFAULT_BORDER_COLOR,
+ border: APPWINDOW_MENU_BORDER_WIDTH,
+ background_color: APPWINDOW_MENU_BACKGROUND_COLOR,
+ padding: 4,
+ corner_radius: APPWINDOW_MENU_CORNER_RADIUS,
+ width: Main.overview._dash.actor.width * 0.75 });
+ this._windowContainer.connect('unselected', Lang.bind(this, this._onItemUnselected));
+ this._windowContainer.connect('selected', Lang.bind(this, this._onItemSelected));
+ this._windowContainer.connect('cancelled', Lang.bind(this, this._onWindowSelectionCancelled));
+ this._windowContainer.connect('activate', Lang.bind(this, this._onItemActivate));
+ this.actor.add_actor(this._windowContainer);
+
+ // Stay popped up on release over application icon
+ this._windowContainer.set_persistent_source(this._source.actor);
+ this._windowContainer.connect('button-release-event', Lang.bind(this, this._onMenuButtonRelease));
+
+ // Chain our visibility and lifecycle to that of the source
+ source.actor.connect('notify::mapped', Lang.bind(this, function () {
+ if (!source.actor.mapped)
+ this._windowContainer.popdown();
+ }));
+ source.actor.connect('destroy', Lang.bind(this, function () { this.actor.destroy(); }));
+
+ global.stage.add_actor(this.actor);
+ },
+
+ _getPreferredWidth: function(actor, forHeight, alloc) {
+ let [min, natural] = this._windowContainer.get_preferred_width(forHeight);
+ alloc.min_size = min;
+ alloc.natural_size = natural;
+ },
+
+ _getPreferredHeight: function(actor, forWidth, alloc) {
+ let [min, natural] = this._windowContainer.get_preferred_height(forWidth);
+ alloc.min_size = min;
+ alloc.natural_size = natural;
+ },
+
+ _allocate: function(actor, box, flags) {
+ let childBox = new Clutter.ActorBox();
+ let width = box.x2 - box.x1;
+ let height = box.y2 - box.y1;
+ childBox.x1 = APPWINDOW_MENU_BORDER_WIDTH;
+ childBox.x2 = width;
+ childBox.y1 = 0;
+ childBox.y2 = height;
+ this._windowContainer.allocate(childBox, flags);
+ },
+
+ _redisplay: function() {
+ this._windowContainer.remove_all();
+ this._windowContainer.show();
+
+ this._appendMenuItem(_("New Window"))._actionType = MenuAction.NONE;
+ this._appendMenuItem(_("Save"))._actionType = MenuAction.NONE;
+ this._appendSeparator();
+ this._appendMenuItem(_("Maximize"))._actionType = MenuAction.MAXIMIZE;
+ this._appendMenuItem(_("Unmaximize"))._actionType = MenuAction.UNMAXIMIZE;
+ this._appendMenuItem(_("Minimize"))._actionType = MenuAction.MINIMIZE;
+ this._appendMenuItem(_("Unminimize"))._actionType = MenuAction.UNMINIMIZE;
+ this._appendMenuItem(_("Close"))._actionType = MenuAction.CLOSE;
+ this._highlightedItem = null;
+ },
+
+ _appendSeparator: function () {
+ let box = new Big.Box({ padding_top: 2, padding_bottom: 2 });
+ box.append(new Clutter.Rectangle({ height: 1,
+ color: APPWINDOW_MENU_SEPARATOR_COLOR }),
+ Big.BoxPackFlags.EXPAND);
+ this._windowContainer.append_separator(box, Big.BoxPackFlags.NONE);
+ },
+
+ _appendMenuItem: function(labelText) {
+ let box = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
+ padding_top: 4,
+ padding_bottom: 4,
+ spacing: 4,
+ reactive: true });
+ let label = new Clutter.Text({ text: labelText,
+ font_name: APPWINDOW_MENU_FONT,
+ ellipsize: Pango.EllipsizeMode.END,
+ color: APPWINDOW_MENU_COLOR });
+ box.append(label, Big.BoxPackFlags.NONE);
+ this._windowContainer.append(box, Big.BoxPackFlags.NONE);
+ return box;
+ },
+
+ popup: function(coords) {
+ this._redisplay();
+ this._windowContainer.popup(1, Main.currentTime());
+ this.actor.set_position(coords[0], coords[1]);
+ this.actor.show();
+ },
+
+ popdown: function() {
+ this._windowContainer.popdown();
+ this.actor.hide();
+ },
+
+ _onMenuButtonRelease: function (actor, event) {
+ if (this._highlightedItem == null) {
+ this.popdown();
+ return;
+ }
+ switch (this._highlightedItem._actionType) {
+ case MenuAction.MAXIMIZE:
+ this._source.metaWindow.maximize(3);
+ break;
+ case MenuAction.UNMAXIMIZE:
+ this._source.metaWindow.unmaximize(3);
+ break;
+ case MenuAction.MINIMIZE:
+ this._source.metaWindow.minimize();
+ break;
+ case MenuAction.UNMINIMIZE:
+ this._source.metaWindow.unminimize();
+ break;
+ case MenuAction.CLOSE:
+ this._source.metaWindow.delete(event.get_time());
+ break;
+ }
+ this.popdown();
+ this._source.updateClone();
+ },
+
+ _updateHighlight: function (item) {
+ if (this._highlightedItem) {
+ this._highlightedItem.background_color = TRANSPARENT_COLOR;
+ }
+ this._highlightedItem = item;
+ if (this._highlightedItem) {
+ this._highlightedItem.background_color = APPWINDOW_MENU_SELECTED_COLOR;
+ }
+ },
+
+ _onItemUnselected: function (actor, child) {
+ this._updateHighlight(null);
+ },
+
+ _onItemSelected: function (actor, child) {
+ this._updateHighlight(child);
+ },
+
+ _onItemActivate: function (actor, child) {
+ this.popdown();
+ },
+
+ _onWindowSelectionCancelled: function () {
+ this.popdown();
+ }
+};
+
+Signals.addSignalMethods(AppWindowMenu.prototype);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]