Merge branch 'workspace-salon'
Conflicts: src/shell-global.c svn path=/trunk/; revision=152
This commit is contained in:
parent
b6ec5080c8
commit
5afcf07782
@ -9,6 +9,8 @@ AC_CONFIG_HEADERS(config.h)
|
|||||||
|
|
||||||
AC_DISABLE_STATIC
|
AC_DISABLE_STATIC
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
|
# Needed for per-target cflags, like in gnomeshell-taskpanel
|
||||||
|
AM_PROG_CC_C_O
|
||||||
AM_PROG_LIBTOOL
|
AM_PROG_LIBTOOL
|
||||||
|
|
||||||
GETTEXT_PACKAGE=gnome-shell
|
GETTEXT_PACKAGE=gnome-shell
|
||||||
@ -16,10 +18,11 @@ AC_SUBST(GETTEXT_PACKAGE)
|
|||||||
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
|
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
|
||||||
[The prefix for our gettext translation domains.])
|
[The prefix for our gettext translation domains.])
|
||||||
|
|
||||||
PKG_CHECK_MODULES(MUTTER_PLUGIN, gtk+-2.0 metacity-plugins gjs-gi-1.0)
|
PKG_CHECK_MODULES(MUTTER_PLUGIN, gtk+-2.0 dbus-glib-1 metacity-plugins gjs-gi-1.0)
|
||||||
PKG_CHECK_MODULES(TIDY, clutter-0.8)
|
PKG_CHECK_MODULES(TIDY, clutter-0.8)
|
||||||
PKG_CHECK_MODULES(BIG, clutter-cairo-0.8 gtk+-2.0 librsvg-2.0)
|
PKG_CHECK_MODULES(BIG, clutter-cairo-0.8 gtk+-2.0 librsvg-2.0)
|
||||||
PKG_CHECK_MODULES(TRAY, gtk+-2.0)
|
PKG_CHECK_MODULES(TRAY, gtk+-2.0)
|
||||||
|
PKG_CHECK_MODULES(TASKPANEL, libwnck-1.0 dbus-glib-1)
|
||||||
# We require libgnomeui for generating thumbnails for recent files with GnomeThumbnailFactory.
|
# We require libgnomeui for generating thumbnails for recent files with GnomeThumbnailFactory.
|
||||||
# We'll switch to using GnomeDesktopThumbnailFactory once the branch of gnome-desktop that contains
|
# We'll switch to using GnomeDesktopThumbnailFactory once the branch of gnome-desktop that contains
|
||||||
# it becomes stable.
|
# it becomes stable.
|
||||||
|
@ -98,6 +98,9 @@ Signals.addSignalMethods(ClutterFrameTicker.prototype);
|
|||||||
function start() {
|
function start() {
|
||||||
let global = Shell.Global.get();
|
let global = Shell.Global.get();
|
||||||
|
|
||||||
|
// Here we grab our DBus name, etc.
|
||||||
|
global.late_init();
|
||||||
|
|
||||||
Tweener.setFrameTicker(new ClutterFrameTicker());
|
Tweener.setFrameTicker(new ClutterFrameTicker());
|
||||||
|
|
||||||
// The background color really only matters if there is no desktop
|
// The background color really only matters if there is no desktop
|
||||||
|
@ -15,6 +15,7 @@ const GdkPixbuf = imports.gi.GdkPixbuf;
|
|||||||
|
|
||||||
// Windows are slightly translucent in the overlay mode
|
// Windows are slightly translucent in the overlay mode
|
||||||
const WINDOW_OPACITY = 0.9 * 255;
|
const WINDOW_OPACITY = 0.9 * 255;
|
||||||
|
const FOCUS_ANIMATION_TIME = 0.15;
|
||||||
|
|
||||||
const WINDOWCLONE_BG_COLOR = new Clutter.Color();
|
const WINDOWCLONE_BG_COLOR = new Clutter.Color();
|
||||||
WINDOWCLONE_BG_COLOR.from_pixel(0x000000f0);
|
WINDOWCLONE_BG_COLOR.from_pixel(0x000000f0);
|
||||||
@ -78,17 +79,24 @@ Workspace.prototype = {
|
|||||||
this._windows = [this._desktop];
|
this._windows = [this._desktop];
|
||||||
for (let i = 0; i < windows.length; i++) {
|
for (let i = 0; i < windows.length; i++) {
|
||||||
if (this._isOverlayWindow(windows[i])) {
|
if (this._isOverlayWindow(windows[i])) {
|
||||||
let clone = this._makeClone(windows[i]);
|
let clone = this._makeClone(windows[i], i);
|
||||||
clone.connect("button-press-event",
|
clone.connect("button-press-event",
|
||||||
function(clone, event) {
|
function(clone, event) {
|
||||||
clone.raise_top();
|
clone.raise_top();
|
||||||
me._activateWindow(clone.realWindow, event.get_time());
|
me._activateWindow(clone.realWindow, event.get_time());
|
||||||
});
|
});
|
||||||
|
clone.connect('enter-event', function (a, e) {
|
||||||
|
me._cloneEnter(clone, e);
|
||||||
|
});
|
||||||
|
clone.connect('leave-event', function (a, e) {
|
||||||
|
me._cloneLeave(clone, e);
|
||||||
|
});
|
||||||
this.actor.add_actor(clone);
|
this.actor.add_actor(clone);
|
||||||
this._windows.push(clone);
|
this._windows.push(clone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._overlappedMode = !((this._windows.length-1) in POSITIONS);
|
||||||
this._removeButton = null;
|
this._removeButton = null;
|
||||||
this._visible = false;
|
this._visible = false;
|
||||||
},
|
},
|
||||||
@ -191,11 +199,7 @@ Workspace.prototype = {
|
|||||||
scale_y: scale,
|
scale_y: scale,
|
||||||
time: Overlay.ANIMATION_TIME,
|
time: Overlay.ANIMATION_TIME,
|
||||||
opacity: WINDOW_OPACITY,
|
opacity: WINDOW_OPACITY,
|
||||||
transition: "easeOutQuad",
|
transition: "easeOutQuad"
|
||||||
onComplete: function () {
|
|
||||||
this._addCloneTitle(window);
|
|
||||||
},
|
|
||||||
onCompleteScope: this
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +226,7 @@ Workspace.prototype = {
|
|||||||
for (let i = 0; i < this._windows.length; i++) {
|
for (let i = 0; i < this._windows.length; i++) {
|
||||||
let window = this._windows[i];
|
let window = this._windows[i];
|
||||||
if (window.cloneTitle)
|
if (window.cloneTitle)
|
||||||
window.cloneTitle.destroy();
|
window.cloneTitle.hide();
|
||||||
Tweener.addTween(window,
|
Tweener.addTween(window,
|
||||||
{ x: this.fullSizeX + window.origX,
|
{ x: this.fullSizeX + window.origX,
|
||||||
y: this.fullSizeY + window.origY,
|
y: this.fullSizeY + window.origY,
|
||||||
@ -250,6 +254,7 @@ Workspace.prototype = {
|
|||||||
// Animates grid shrinking/expanding when a row or column
|
// Animates grid shrinking/expanding when a row or column
|
||||||
// of workspaces is added or removed
|
// of workspaces is added or removed
|
||||||
resizeToGrid : function (oldScale) {
|
resizeToGrid : function (oldScale) {
|
||||||
|
let me = this;
|
||||||
let rescale = this.scale / oldScale;
|
let rescale = this.scale / oldScale;
|
||||||
|
|
||||||
for (let i = 0; i < this._windows.length; i++) {
|
for (let i = 0; i < this._windows.length; i++) {
|
||||||
@ -263,10 +268,12 @@ Workspace.prototype = {
|
|||||||
scale_x: newWindowScale,
|
scale_x: newWindowScale,
|
||||||
scale_y: newWindowScale,
|
scale_y: newWindowScale,
|
||||||
time: Overlay.ANIMATION_TIME,
|
time: Overlay.ANIMATION_TIME,
|
||||||
transition: "easeOutQuad"
|
transition: "easeOutQuad",
|
||||||
|
onComplete: function () {
|
||||||
|
me._adjustCloneTitle(me._windows[i]);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this._adjustCloneTitle(this._windows[i], newX, newY,
|
|
||||||
newWindowScale);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._removeButton) {
|
if (this._removeButton) {
|
||||||
@ -364,12 +371,15 @@ Workspace.prototype = {
|
|||||||
|
|
||||||
// Tests if @win should be shown in the overlay
|
// Tests if @win should be shown in the overlay
|
||||||
_isOverlayWindow : function (win) {
|
_isOverlayWindow : function (win) {
|
||||||
return win.get_window_type() != Meta.WindowType.DESKTOP &&
|
let wintype = win.get_window_type();
|
||||||
!win.is_override_redirect();
|
if (wintype == Meta.WindowType.DESKTOP ||
|
||||||
|
wintype == Meta.WindowType.DOCK)
|
||||||
|
return false;
|
||||||
|
return !win.is_override_redirect();
|
||||||
},
|
},
|
||||||
|
|
||||||
// Create a clone of a window to use in the overlay.
|
// Create a clone of a window to use in the overlay.
|
||||||
_makeClone : function(window) {
|
_makeClone : function(window, index) {
|
||||||
let clone = new Clutter.CloneTexture({ parent_texture: window.get_texture(),
|
let clone = new Clutter.CloneTexture({ parent_texture: window.get_texture(),
|
||||||
reactive: true,
|
reactive: true,
|
||||||
x: window.x,
|
x: window.x,
|
||||||
@ -377,6 +387,7 @@ Workspace.prototype = {
|
|||||||
clone.realWindow = window;
|
clone.realWindow = window;
|
||||||
clone.origX = window.x;
|
clone.origX = window.x;
|
||||||
clone.origY = window.y;
|
clone.origY = window.y;
|
||||||
|
clone.index = index;
|
||||||
return clone;
|
return clone;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -423,46 +434,67 @@ Workspace.prototype = {
|
|||||||
return [xCenter, yCenter, fraction];
|
return [xCenter, yCenter, fraction];
|
||||||
},
|
},
|
||||||
|
|
||||||
_addCloneTitle : function (clone) {
|
_cloneEnter: function (clone, event) {
|
||||||
let transformed = clone.get_transformed_size();
|
if (!clone.cloneTitle)
|
||||||
|
this._createCloneTitle(clone);
|
||||||
|
clone.cloneTitle.show();
|
||||||
|
this._adjustCloneTitle(clone)
|
||||||
|
if (!this._overlappedMode)
|
||||||
|
return;
|
||||||
|
if (clone.index != this._windows.length-1) {
|
||||||
|
clone.raise_top();
|
||||||
|
clone.cloneTitle.raise(clone);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_cloneLeave: function (clone, event) {
|
||||||
|
clone.cloneTitle.hide();
|
||||||
|
if (!this._overlappedMode)
|
||||||
|
return;
|
||||||
|
if (clone.index != this._windows.length-1) {
|
||||||
|
clone.lower(this._windows[clone.index+1]);
|
||||||
|
clone.cloneTitle.raise(clone);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_createCloneTitle : function (clone) {
|
||||||
|
let me = this;
|
||||||
let window = clone.realWindow;
|
let window = clone.realWindow;
|
||||||
let icon = window.meta_window.mini_icon;
|
|
||||||
let iconTexture = new Clutter.Texture({ width: 16, height: 16, keep_aspect_ratio: true});
|
|
||||||
Shell.clutter_texture_set_from_pixbuf(iconTexture, icon);
|
|
||||||
let box = new Big.Box({background_color : WINDOWCLONE_BG_COLOR,
|
let box = new Big.Box({background_color : WINDOWCLONE_BG_COLOR,
|
||||||
y_align: Big.BoxAlignment.CENTER,
|
y_align: Big.BoxAlignment.CENTER,
|
||||||
corner_radius: 5,
|
corner_radius: 5,
|
||||||
padding: 4,
|
padding: 4,
|
||||||
spacing: 4,
|
spacing: 4,
|
||||||
orientation: Big.BoxOrientation.HORIZONTAL});
|
orientation: Big.BoxOrientation.HORIZONTAL});
|
||||||
|
|
||||||
|
let icon = window.meta_window.mini_icon;
|
||||||
|
let iconTexture = new Clutter.Texture({ x: clone.x,
|
||||||
|
y: clone.y + clone.height - 16,
|
||||||
|
width: 16, height: 16, keep_aspect_ratio: true});
|
||||||
|
Shell.clutter_texture_set_from_pixbuf(iconTexture, icon);
|
||||||
box.append(iconTexture, Big.BoxPackFlags.NONE);
|
box.append(iconTexture, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
let title = new Clutter.Label({color: WINDOWCLONE_TITLE_COLOR,
|
let title = new Clutter.Label({color: WINDOWCLONE_TITLE_COLOR,
|
||||||
font_name: "Sans 14",
|
font_name: "Sans 12",
|
||||||
text: window.meta_window.title,
|
text: window.meta_window.title,
|
||||||
ellipsize: Pango.EllipsizeMode.END});
|
ellipsize: Pango.EllipsizeMode.END});
|
||||||
// Get current width (just the icon), with spacing, plus title
|
|
||||||
box.fullWidth = box.width + box.spacing + title.width;
|
|
||||||
box.width = Math.min(box.fullWidth, transformed[0]);
|
|
||||||
box.append(title, Big.BoxPackFlags.EXPAND);
|
box.append(title, Big.BoxPackFlags.EXPAND);
|
||||||
box.set_position(clone.x, clone.y);
|
// Get and cache the expected width (just the icon), with spacing, plus title
|
||||||
let parent = clone.get_parent();
|
box.fullWidth = box.width;
|
||||||
|
box.hide(); // Hidden by default, show on mouseover
|
||||||
clone.cloneTitle = box;
|
clone.cloneTitle = box;
|
||||||
|
|
||||||
|
let parent = clone.get_parent();
|
||||||
parent.add_actor(box);
|
parent.add_actor(box);
|
||||||
},
|
},
|
||||||
|
|
||||||
_adjustCloneTitle : function (clone, newX, newY, newScale) {
|
_adjustCloneTitle : function (clone) {
|
||||||
|
let transformed = clone.get_transformed_size();
|
||||||
let title = clone.cloneTitle;
|
let title = clone.cloneTitle;
|
||||||
if (!title)
|
title.width = Math.min(title.fullWidth, transformed[0]);
|
||||||
return;
|
let xoff = (transformed[0] - title.width)/2;
|
||||||
|
title.set_position(clone.x+xoff, clone.y);
|
||||||
let newWidth = Math.min(title.fullWidth, clone.width * newScale);
|
|
||||||
Tweener.addTween(title,
|
|
||||||
{ x: newX,
|
|
||||||
y: newY,
|
|
||||||
width: newWidth,
|
|
||||||
time: Overlay.ANIMATION_TIME,
|
|
||||||
transition: "easeOutQuad"
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_activateWindow : function(w, time) {
|
_activateWindow : function(w, time) {
|
||||||
|
17
src/Makefile-taskpanel.am
Normal file
17
src/Makefile-taskpanel.am
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
gnomeshell_taskpanel_CPPFLAGS = \
|
||||||
|
-I$(top_srcdir)/src \
|
||||||
|
-DG_DISABLE_DEPRECATED \
|
||||||
|
-DWNCK_I_KNOW_THIS_IS_UNSTABLE \
|
||||||
|
-DG_LOG_DOMAIN=\"gnomeshell-taskpanel\" \
|
||||||
|
$(TASKPANEL_CFLAGS) \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
gnomeshell_taskpanel_SOURCES = \
|
||||||
|
gnomeshell-taskpanel.c \
|
||||||
|
shell-panel-window.c \
|
||||||
|
shell-panel-window.h \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
gnomeshell_taskpanel_LDADD = $(TASKPANEL_LIBS)
|
||||||
|
|
||||||
|
bin_PROGRAMS += gnomeshell-taskpanel
|
@ -2,11 +2,13 @@ NULL =
|
|||||||
BUILT_SOURCES =
|
BUILT_SOURCES =
|
||||||
CLEANFILES =
|
CLEANFILES =
|
||||||
EXTRA_DIST =
|
EXTRA_DIST =
|
||||||
|
bin_PROGRAMS =
|
||||||
noinst_LTLIBRARIES =
|
noinst_LTLIBRARIES =
|
||||||
|
|
||||||
include Makefile-tidy.am
|
include Makefile-tidy.am
|
||||||
include Makefile-big.am
|
include Makefile-big.am
|
||||||
include Makefile-tray.am
|
include Makefile-tray.am
|
||||||
|
include Makefile-taskpanel.am
|
||||||
|
|
||||||
gnome_shell_cflags = \
|
gnome_shell_cflags = \
|
||||||
$(MUTTER_PLUGIN_CFLAGS) \
|
$(MUTTER_PLUGIN_CFLAGS) \
|
||||||
|
70
src/gnomeshell-taskpanel.c
Normal file
70
src/gnomeshell-taskpanel.c
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
#include "shell-panel-window.h"
|
||||||
|
#include <libwnck/libwnck.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <dbus/dbus-glib.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_name_owner_changed (DBusGProxy *proxy,
|
||||||
|
const char *name,
|
||||||
|
const char *prev_owner,
|
||||||
|
const char *new_owner,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
if (strcmp (name, "org.gnome.Shell") == 0 && new_owner[0] == '\0')
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
monitor_main_shell ()
|
||||||
|
{
|
||||||
|
DBusGConnection *session;
|
||||||
|
DBusGProxy *driver;
|
||||||
|
|
||||||
|
session = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
|
||||||
|
|
||||||
|
driver = dbus_g_proxy_new_for_name (session,
|
||||||
|
DBUS_SERVICE_DBUS,
|
||||||
|
DBUS_PATH_DBUS,
|
||||||
|
DBUS_INTERFACE_DBUS);
|
||||||
|
|
||||||
|
dbus_g_proxy_add_signal (driver,
|
||||||
|
"NameOwnerChanged",
|
||||||
|
G_TYPE_STRING,
|
||||||
|
G_TYPE_STRING,
|
||||||
|
G_TYPE_STRING,
|
||||||
|
G_TYPE_INVALID);
|
||||||
|
|
||||||
|
dbus_g_proxy_connect_signal (driver,
|
||||||
|
"NameOwnerChanged",
|
||||||
|
G_CALLBACK (on_name_owner_changed),
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
ShellPanelWindow *panel;
|
||||||
|
WnckScreen *screen;
|
||||||
|
WnckTasklist *tasks;
|
||||||
|
|
||||||
|
gtk_init (&argc, &argv);
|
||||||
|
|
||||||
|
monitor_main_shell ();
|
||||||
|
|
||||||
|
panel = shell_panel_window_new ();
|
||||||
|
|
||||||
|
screen = wnck_screen_get_default();
|
||||||
|
tasks = WNCK_TASKLIST (wnck_tasklist_new (screen));
|
||||||
|
|
||||||
|
gtk_container_add (GTK_CONTAINER (panel), GTK_WIDGET (tasks));
|
||||||
|
|
||||||
|
gtk_widget_show_all (GTK_WIDGET (panel));
|
||||||
|
|
||||||
|
gtk_main ();
|
||||||
|
|
||||||
|
exit (0);
|
||||||
|
}
|
@ -7,8 +7,11 @@
|
|||||||
#include <clutter/x11/clutter-x11.h>
|
#include <clutter/x11/clutter-x11.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <libgnomeui-2.0/libgnomeui/gnome-thumbnail.h>
|
||||||
|
#include <dbus/dbus-glib.h>
|
||||||
#include <libgnomeui/gnome-thumbnail.h>
|
#include <libgnomeui/gnome-thumbnail.h>
|
||||||
|
|
||||||
struct _ShellGlobal {
|
struct _ShellGlobal {
|
||||||
@ -456,3 +459,49 @@ shell_global_reexec_self (ShellGlobal *global)
|
|||||||
g_warning ("failed to reexec: %s", g_strerror (errno));
|
g_warning ("failed to reexec: %s", g_strerror (errno));
|
||||||
g_ptr_array_free (arr, TRUE);
|
g_ptr_array_free (arr, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shell_global_late_init
|
||||||
|
*
|
||||||
|
* Perform once-only global initialization; currently this executes
|
||||||
|
* the external tasklist process and grabs the org.gnome.Shell DBus name.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
shell_global_late_init (ShellGlobal *global)
|
||||||
|
{
|
||||||
|
static gboolean initialized = FALSE;
|
||||||
|
GError *error = NULL;
|
||||||
|
DBusGConnection *session;
|
||||||
|
DBusGProxy *bus;
|
||||||
|
guint32 request_name_result;
|
||||||
|
const char* panel_args[] = {"gnomeshell-taskpanel", NULL};
|
||||||
|
|
||||||
|
if (initialized)
|
||||||
|
return;
|
||||||
|
initialized = TRUE;
|
||||||
|
|
||||||
|
session = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
|
||||||
|
|
||||||
|
bus = dbus_g_proxy_new_for_name (session,
|
||||||
|
DBUS_SERVICE_DBUS,
|
||||||
|
DBUS_PATH_DBUS,
|
||||||
|
DBUS_INTERFACE_DBUS);
|
||||||
|
|
||||||
|
if (!dbus_g_proxy_call (bus, "RequestName", &error,
|
||||||
|
G_TYPE_STRING, "org.gnome.Shell",
|
||||||
|
G_TYPE_UINT, 0,
|
||||||
|
G_TYPE_INVALID,
|
||||||
|
G_TYPE_UINT, &request_name_result,
|
||||||
|
G_TYPE_INVALID)) {
|
||||||
|
g_print ("failed to acquire org.gnome.Shell: %s\n", error->message);
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_spawn_async (NULL, &panel_args, NULL, G_SPAWN_SEARCH_PATH, NULL,
|
||||||
|
NULL, NULL, &error)) {
|
||||||
|
g_critical ("failed to execute %s: %s", panel_args[0], error->message);
|
||||||
|
g_clear_error (&error);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (bus);
|
||||||
|
}
|
@ -38,6 +38,8 @@ GdkPixbuf *shell_get_thumbnail_for_recent_info(GtkRecentInfo *recent_info);
|
|||||||
|
|
||||||
ShellGlobal *shell_global_get (void);
|
ShellGlobal *shell_global_get (void);
|
||||||
|
|
||||||
|
void shell_global_late_init (ShellGlobal *global);
|
||||||
|
|
||||||
void shell_global_set_stage_input_area (ShellGlobal *global,
|
void shell_global_set_stage_input_area (ShellGlobal *global,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
|
260
src/shell-panel-window.c
Normal file
260
src/shell-panel-window.c
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
#include "shell-panel-window.h"
|
||||||
|
|
||||||
|
#include <gdk/gdkx.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
|
#define PANEL_HEIGHT 25
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static void shell_panel_window_dispose (GObject *object);
|
||||||
|
static void shell_panel_window_finalize (GObject *object);
|
||||||
|
static void shell_panel_window_set_property ( GObject *object,
|
||||||
|
guint property_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec );
|
||||||
|
static void shell_panel_window_get_property( GObject *object,
|
||||||
|
guint property_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec );
|
||||||
|
static void shell_panel_window_size_request (GtkWidget *self, GtkRequisition *req);
|
||||||
|
static void shell_panel_window_size_allocate (GtkWidget *self, GtkAllocation *allocation);
|
||||||
|
static void shell_panel_window_realize (GtkWidget *self);
|
||||||
|
static void shell_panel_window_show (GtkWidget *self);
|
||||||
|
static void set_strut (ShellPanelWindow *self);
|
||||||
|
static void on_workarea_changed (ShellPanelWindow *self);
|
||||||
|
static void handle_new_workarea (ShellPanelWindow *self);
|
||||||
|
static GdkFilterReturn filter_func (GdkXEvent *xevent,
|
||||||
|
GdkEvent *event,
|
||||||
|
gpointer data);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(ShellPanelWindow, shell_panel_window, GTK_TYPE_WINDOW);
|
||||||
|
|
||||||
|
struct ShellPanelWindowPrivate {
|
||||||
|
GtkAllocation workarea;
|
||||||
|
guint width;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_panel_window_class_init(ShellPanelWindowClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = (GObjectClass *)klass;
|
||||||
|
GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
|
||||||
|
|
||||||
|
gobject_class->dispose = shell_panel_window_dispose;
|
||||||
|
gobject_class->finalize = shell_panel_window_finalize;
|
||||||
|
gobject_class->set_property = shell_panel_window_set_property;
|
||||||
|
gobject_class->get_property = shell_panel_window_get_property;
|
||||||
|
|
||||||
|
widget_class->realize = shell_panel_window_realize;
|
||||||
|
widget_class->size_request = shell_panel_window_size_request;
|
||||||
|
widget_class->size_allocate = shell_panel_window_size_allocate;
|
||||||
|
widget_class->show = shell_panel_window_show;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void shell_panel_window_init (ShellPanelWindow *self)
|
||||||
|
{
|
||||||
|
self->priv = g_new0 (ShellPanelWindowPrivate, 1);
|
||||||
|
|
||||||
|
gtk_window_set_type_hint (GTK_WINDOW (self), GDK_WINDOW_TYPE_HINT_DOCK);
|
||||||
|
gtk_window_set_focus_on_map (GTK_WINDOW (self), FALSE);
|
||||||
|
gdk_window_add_filter (NULL, filter_func, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void shell_panel_window_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
ShellPanelWindow *self = (ShellPanelWindow*)object;
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (shell_panel_window_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void shell_panel_window_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
ShellPanelWindow *self = (ShellPanelWindow*)object;
|
||||||
|
|
||||||
|
g_free (self->priv);
|
||||||
|
g_signal_handlers_destroy(object);
|
||||||
|
G_OBJECT_CLASS (shell_panel_window_parent_class)->finalize(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void shell_panel_window_set_property ( GObject *object,
|
||||||
|
guint property_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec )
|
||||||
|
{
|
||||||
|
ShellPanelWindow* self = SHELL_PANEL_WINDOW(object);
|
||||||
|
switch (property_id) {
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void shell_panel_window_get_property ( GObject *object,
|
||||||
|
guint property_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec )
|
||||||
|
{
|
||||||
|
ShellPanelWindow* self = SHELL_PANEL_WINDOW(object);
|
||||||
|
switch (property_id) {
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShellPanelWindow* shell_panel_window_new(void)
|
||||||
|
{
|
||||||
|
return (ShellPanelWindow*) g_object_new(SHELL_TYPE_PANEL_WINDOW,
|
||||||
|
"type", GTK_WINDOW_TOPLEVEL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_strut (ShellPanelWindow *self)
|
||||||
|
{
|
||||||
|
long *buf;
|
||||||
|
int x, y;
|
||||||
|
int strut_size;
|
||||||
|
|
||||||
|
strut_size = GTK_WIDGET (self)->allocation.height;
|
||||||
|
|
||||||
|
gtk_window_get_position (GTK_WINDOW (self), &x, &y);
|
||||||
|
|
||||||
|
buf = g_new0(long, 4);
|
||||||
|
buf[3] = strut_size;
|
||||||
|
gdk_property_change (GTK_WIDGET (self)->window, gdk_atom_intern_static_string ("_NET_WM_STRUT"),
|
||||||
|
gdk_atom_intern_static_string ("CARDINAL"), 32,
|
||||||
|
GDK_PROP_MODE_REPLACE,
|
||||||
|
(guchar*) buf, 4);
|
||||||
|
g_free (buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_panel_window_size_request (GtkWidget *widget, GtkRequisition *requisition)
|
||||||
|
{
|
||||||
|
ShellPanelWindow *self = SHELL_PANEL_WINDOW (widget);
|
||||||
|
GTK_WIDGET_CLASS (shell_panel_window_parent_class)->size_request(widget, requisition);
|
||||||
|
requisition->width = self->priv->width;
|
||||||
|
requisition->height = PANEL_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_panel_window_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
|
||||||
|
{
|
||||||
|
ShellPanelWindow *self = SHELL_PANEL_WINDOW (widget);
|
||||||
|
GTK_WIDGET_CLASS (shell_panel_window_parent_class)->size_allocate(widget, allocation);
|
||||||
|
if (GTK_WIDGET_REALIZED (self))
|
||||||
|
set_strut (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_panel_window_realize (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
ShellPanelWindow *self = SHELL_PANEL_WINDOW (widget);
|
||||||
|
GTK_WIDGET_CLASS (shell_panel_window_parent_class)->realize(widget);
|
||||||
|
set_strut (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_panel_window_show (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
ShellPanelWindow *self = SHELL_PANEL_WINDOW (widget);
|
||||||
|
on_workarea_changed (self);
|
||||||
|
GTK_WIDGET_CLASS (shell_panel_window_parent_class)->show(widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_new_workarea (ShellPanelWindow *self)
|
||||||
|
{
|
||||||
|
int monitor;
|
||||||
|
GtkRequisition requisition;
|
||||||
|
GdkRectangle monitor_geometry;
|
||||||
|
int x, y;
|
||||||
|
int width;
|
||||||
|
|
||||||
|
monitor = gdk_screen_get_monitor_at_point (gdk_screen_get_default (),
|
||||||
|
self->priv->workarea.x,
|
||||||
|
self->priv->workarea.y);
|
||||||
|
gdk_screen_get_monitor_geometry (gdk_screen_get_default (),
|
||||||
|
monitor, &monitor_geometry);
|
||||||
|
gtk_widget_size_request (GTK_WIDGET (self), &requisition);
|
||||||
|
|
||||||
|
x = self->priv->workarea.x;
|
||||||
|
y = monitor_geometry.y + monitor_geometry.height - requisition.height;
|
||||||
|
width = monitor_geometry.width - x;
|
||||||
|
|
||||||
|
self->priv->width = width;
|
||||||
|
gtk_widget_set_size_request (GTK_WIDGET (self), width, PANEL_HEIGHT);
|
||||||
|
gtk_window_move (GTK_WINDOW (self), x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_workarea_changed (ShellPanelWindow *self)
|
||||||
|
{
|
||||||
|
gulong bytes_after, nitems;
|
||||||
|
Atom type;
|
||||||
|
gint format;
|
||||||
|
guchar *data;
|
||||||
|
long *data32;
|
||||||
|
Atom workarea = gdk_x11_get_xatom_by_name_for_display (gdk_display_get_default (), "_NET_WORKAREA");
|
||||||
|
|
||||||
|
XGetWindowProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW(),
|
||||||
|
workarea,
|
||||||
|
0, 4, FALSE, workarea,
|
||||||
|
&type, &format, &nitems, &bytes_after, &data);
|
||||||
|
if ((format == 32) && (nitems == 4) && (bytes_after == 0)) {
|
||||||
|
int x, y, width, height;
|
||||||
|
data32 = (long*)data;
|
||||||
|
x = data32[0]; y = data32[1];
|
||||||
|
width = data32[2]; height = data32[3];
|
||||||
|
if (x == self->priv->workarea.x &&
|
||||||
|
y == self->priv->workarea.y &&
|
||||||
|
width == self->priv->workarea.width &&
|
||||||
|
height == self->priv->workarea.height)
|
||||||
|
return;
|
||||||
|
|
||||||
|
self->priv->workarea.x = x;
|
||||||
|
self->priv->workarea.y = y;
|
||||||
|
self->priv->workarea.width = width;
|
||||||
|
self->priv->workarea.height = height;
|
||||||
|
|
||||||
|
handle_new_workarea (self);
|
||||||
|
} else if (nitems == 0) {
|
||||||
|
self->priv->workarea.x = self->priv->workarea.y = 0;
|
||||||
|
self->priv->workarea.width = self->priv->workarea.height = -1;
|
||||||
|
handle_new_workarea (self);
|
||||||
|
} else {
|
||||||
|
g_printerr ("unexpected return from XGetWindowProperty: %d %ld %ld\n",
|
||||||
|
format, nitems, bytes_after);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkFilterReturn
|
||||||
|
filter_func (GdkXEvent *gdk_xevent,
|
||||||
|
GdkEvent *event,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
ShellPanelWindow *self = SHELL_PANEL_WINDOW (data);
|
||||||
|
GdkFilterReturn ret = GDK_FILTER_CONTINUE;
|
||||||
|
XEvent *xevent = (XEvent *) event;
|
||||||
|
Atom workarea = gdk_x11_get_xatom_by_name_for_display (gdk_display_get_default (), "_NET_WORKAREA");
|
||||||
|
|
||||||
|
switch (xevent->type) {
|
||||||
|
case PropertyNotify:
|
||||||
|
{
|
||||||
|
if (xevent->xproperty.atom != workarea)
|
||||||
|
break;
|
||||||
|
|
||||||
|
on_workarea_changed (self);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
35
src/shell-panel-window.h
Normal file
35
src/shell-panel-window.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef __SHELL_PANEL_WINDOW_H__
|
||||||
|
#define __SHELL_PANEL_WINDOW_H__
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#define SHELL_TYPE_PANEL_WINDOW (shell_panel_window_get_type ())
|
||||||
|
#define SHELL_PANEL_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHELL_TYPE_PANEL_WINDOW, ShellPanelWindow))
|
||||||
|
#define SHELL_PANEL_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_PANEL_WINDOW, ShellPanelWindowClass))
|
||||||
|
#define SHELL_IS_PANEL_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SHELL_TYPE_PANEL_WINDOW))
|
||||||
|
#define SHELL_IS_PANEL_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_PANEL_WINDOW))
|
||||||
|
#define SHELL_PANEL_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_PANEL_WINDOW, ShellPanelWindowClass))
|
||||||
|
|
||||||
|
typedef struct _ShellPanelWindow ShellPanelWindow;
|
||||||
|
typedef struct _ShellPanelWindowClass ShellPanelWindowClass;
|
||||||
|
|
||||||
|
typedef struct ShellPanelWindowPrivate ShellPanelWindowPrivate;
|
||||||
|
|
||||||
|
struct _ShellPanelWindow
|
||||||
|
{
|
||||||
|
GtkWindow parent;
|
||||||
|
|
||||||
|
ShellPanelWindowPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ShellPanelWindowClass
|
||||||
|
{
|
||||||
|
GtkWindowClass parent_class;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
GType shell_panel_window_get_type (void) G_GNUC_CONST;
|
||||||
|
ShellPanelWindow* shell_panel_window_new(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __SHELL_PANEL_WINDOW_H__ */
|
Loading…
Reference in New Issue
Block a user