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_PROG_CC
|
||||
# Needed for per-target cflags, like in gnomeshell-taskpanel
|
||||
AM_PROG_CC_C_O
|
||||
AM_PROG_LIBTOOL
|
||||
|
||||
GETTEXT_PACKAGE=gnome-shell
|
||||
@ -16,10 +18,11 @@ AC_SUBST(GETTEXT_PACKAGE)
|
||||
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
|
||||
[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(BIG, clutter-cairo-0.8 gtk+-2.0 librsvg-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'll switch to using GnomeDesktopThumbnailFactory once the branch of gnome-desktop that contains
|
||||
# it becomes stable.
|
||||
|
@ -98,6 +98,9 @@ Signals.addSignalMethods(ClutterFrameTicker.prototype);
|
||||
function start() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
// Here we grab our DBus name, etc.
|
||||
global.late_init();
|
||||
|
||||
Tweener.setFrameTicker(new ClutterFrameTicker());
|
||||
|
||||
// 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
|
||||
const WINDOW_OPACITY = 0.9 * 255;
|
||||
const FOCUS_ANIMATION_TIME = 0.15;
|
||||
|
||||
const WINDOWCLONE_BG_COLOR = new Clutter.Color();
|
||||
WINDOWCLONE_BG_COLOR.from_pixel(0x000000f0);
|
||||
@ -78,17 +79,24 @@ Workspace.prototype = {
|
||||
this._windows = [this._desktop];
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
if (this._isOverlayWindow(windows[i])) {
|
||||
let clone = this._makeClone(windows[i]);
|
||||
let clone = this._makeClone(windows[i], i);
|
||||
clone.connect("button-press-event",
|
||||
function(clone, event) {
|
||||
clone.raise_top();
|
||||
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._windows.push(clone);
|
||||
}
|
||||
}
|
||||
|
||||
this._overlappedMode = !((this._windows.length-1) in POSITIONS);
|
||||
this._removeButton = null;
|
||||
this._visible = false;
|
||||
},
|
||||
@ -191,11 +199,7 @@ Workspace.prototype = {
|
||||
scale_y: scale,
|
||||
time: Overlay.ANIMATION_TIME,
|
||||
opacity: WINDOW_OPACITY,
|
||||
transition: "easeOutQuad",
|
||||
onComplete: function () {
|
||||
this._addCloneTitle(window);
|
||||
},
|
||||
onCompleteScope: this
|
||||
transition: "easeOutQuad"
|
||||
});
|
||||
}
|
||||
|
||||
@ -222,7 +226,7 @@ Workspace.prototype = {
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
let window = this._windows[i];
|
||||
if (window.cloneTitle)
|
||||
window.cloneTitle.destroy();
|
||||
window.cloneTitle.hide();
|
||||
Tweener.addTween(window,
|
||||
{ x: this.fullSizeX + window.origX,
|
||||
y: this.fullSizeY + window.origY,
|
||||
@ -250,6 +254,7 @@ Workspace.prototype = {
|
||||
// Animates grid shrinking/expanding when a row or column
|
||||
// of workspaces is added or removed
|
||||
resizeToGrid : function (oldScale) {
|
||||
let me = this;
|
||||
let rescale = this.scale / oldScale;
|
||||
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
@ -263,10 +268,12 @@ Workspace.prototype = {
|
||||
scale_x: newWindowScale,
|
||||
scale_y: newWindowScale,
|
||||
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) {
|
||||
@ -364,12 +371,15 @@ Workspace.prototype = {
|
||||
|
||||
// Tests if @win should be shown in the overlay
|
||||
_isOverlayWindow : function (win) {
|
||||
return win.get_window_type() != Meta.WindowType.DESKTOP &&
|
||||
!win.is_override_redirect();
|
||||
let wintype = win.get_window_type();
|
||||
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.
|
||||
_makeClone : function(window) {
|
||||
_makeClone : function(window, index) {
|
||||
let clone = new Clutter.CloneTexture({ parent_texture: window.get_texture(),
|
||||
reactive: true,
|
||||
x: window.x,
|
||||
@ -377,6 +387,7 @@ Workspace.prototype = {
|
||||
clone.realWindow = window;
|
||||
clone.origX = window.x;
|
||||
clone.origY = window.y;
|
||||
clone.index = index;
|
||||
return clone;
|
||||
},
|
||||
|
||||
@ -423,46 +434,67 @@ Workspace.prototype = {
|
||||
return [xCenter, yCenter, fraction];
|
||||
},
|
||||
|
||||
_addCloneTitle : function (clone) {
|
||||
let transformed = clone.get_transformed_size();
|
||||
_cloneEnter: function (clone, event) {
|
||||
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 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,
|
||||
y_align: Big.BoxAlignment.CENTER,
|
||||
corner_radius: 5,
|
||||
padding: 4,
|
||||
spacing: 4,
|
||||
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);
|
||||
|
||||
let title = new Clutter.Label({color: WINDOWCLONE_TITLE_COLOR,
|
||||
font_name: "Sans 14",
|
||||
font_name: "Sans 12",
|
||||
text: window.meta_window.title,
|
||||
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.set_position(clone.x, clone.y);
|
||||
let parent = clone.get_parent();
|
||||
// Get and cache the expected width (just the icon), with spacing, plus title
|
||||
box.fullWidth = box.width;
|
||||
box.hide(); // Hidden by default, show on mouseover
|
||||
clone.cloneTitle = box;
|
||||
|
||||
let parent = clone.get_parent();
|
||||
parent.add_actor(box);
|
||||
},
|
||||
|
||||
_adjustCloneTitle : function (clone, newX, newY, newScale) {
|
||||
_adjustCloneTitle : function (clone) {
|
||||
let transformed = clone.get_transformed_size();
|
||||
let title = clone.cloneTitle;
|
||||
if (!title)
|
||||
return;
|
||||
|
||||
let newWidth = Math.min(title.fullWidth, clone.width * newScale);
|
||||
Tweener.addTween(title,
|
||||
{ x: newX,
|
||||
y: newY,
|
||||
width: newWidth,
|
||||
time: Overlay.ANIMATION_TIME,
|
||||
transition: "easeOutQuad"
|
||||
});
|
||||
title.width = Math.min(title.fullWidth, transformed[0]);
|
||||
let xoff = (transformed[0] - title.width)/2;
|
||||
title.set_position(clone.x+xoff, clone.y);
|
||||
},
|
||||
|
||||
_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 =
|
||||
CLEANFILES =
|
||||
EXTRA_DIST =
|
||||
bin_PROGRAMS =
|
||||
noinst_LTLIBRARIES =
|
||||
|
||||
include Makefile-tidy.am
|
||||
include Makefile-big.am
|
||||
include Makefile-tray.am
|
||||
include Makefile-taskpanel.am
|
||||
|
||||
gnome_shell_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 <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <libgnomeui-2.0/libgnomeui/gnome-thumbnail.h>
|
||||
#include <dbus/dbus-glib.h>
|
||||
#include <libgnomeui/gnome-thumbnail.h>
|
||||
|
||||
struct _ShellGlobal {
|
||||
@ -456,3 +459,49 @@ shell_global_reexec_self (ShellGlobal *global)
|
||||
g_warning ("failed to reexec: %s", g_strerror (errno));
|
||||
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);
|
||||
|
||||
void shell_global_late_init (ShellGlobal *global);
|
||||
|
||||
void shell_global_set_stage_input_area (ShellGlobal *global,
|
||||
int x,
|
||||
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