update to trunk

This commit is contained in:
Tom Beckmann 2014-04-19 14:06:11 +02:00
commit b6a714034c
64 changed files with 4285 additions and 2200 deletions

View File

@ -1 +1,41 @@
aclocal.m4
autom4te.cache
/build-aux/*
ChangeLog
config.h
config.h.in
config.log
config.status
configure
intltool-extract.in
intltool-merge.in
intltool-update.in
libtool
m4
mkinstalldirs
stamp-h1
Makefile
Makefile.in
.version
.deps
.dirstamp
.libs
*.c
*.h
*.lo
*.la
*.pc
*.stamp
data/gala.desktop
data/gschemas.compiled
data/org.pantheon.desktop.gala.gschema.valid
data/org.pantheon.desktop.gala.gschema.xml
data/org.pantheon.desktop.gala.gschema.xml.in
lib/gala.vapi
po/*.gmo
po/.intltool-merge-cache
po/Makefile.in.in
po/POTFILES
po/stamp-it
src/gala
build

8
AUTHORS Normal file
View File

@ -0,0 +1,8 @@
Cody Garver <cody@elementaryos.org>
Daniel Fore <daniel@elementaryos.org>
Garden Gnome <gardengnome85@gmail.com>
Niels Avonds <niels.avonds@gmail.com>
Rico Tzschichholz <ricotz@ubuntu.com>
Sergey "Shnatsel" Davidoff <sergey@elementaryos.org>
Timo Reimerdes <sedremier@gmail.com>
Tom Beckmann <tomjonabc@gmail.com>

View File

@ -1,133 +0,0 @@
# Check http://webdev.elementaryos.org/docs/developer-guide/cmake for documentation
project (gala)
cmake_minimum_required (VERSION 2.8)
cmake_policy (VERSION 2.6)
list (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/vala)
#
# Base bits
#
enable_testing ()
set (DATADIR "${CMAKE_INSTALL_PREFIX}/share")
set (PKGDATADIR "${DATADIR}/gala")
set (GETTEXT_PACKAGE "gala")
set (RELEASE_NAME "")
set (VERSION "0.1.0")
set (VERSION_INFO "Release")
set (CMAKE_C_FLAGS "-ggdb")
set (PREFIX ${CMAKE_INSTALL_PREFIX})
set (DOLLAR "$")
set(CPACK_SOURCE_GENERATOR "TBZ2")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${VERSION}")
set(CPACK_SOURCE_IGNORE_FILES "/build/;/.bzr/;~$;.bzrignore;${CPACK_SOURCE_IGNORE_FILES}")
include(CPack)
add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source)
list (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
configure_file (${CMAKE_SOURCE_DIR}/src/Config.vala.cmake ${CMAKE_BINARY_DIR}/src/Config.vala)
add_definitions(-DGETTEXT_PACKAGE=\"${GETTEXT_PACKAGE}\" -DGNOME_DESKTOP_USE_UNSTABLE_API -w)
find_package(PkgConfig)
pkg_check_modules(DEPS REQUIRED libmutter>=3.4 granite clutter-1.0>=1.9.16 clutter-gtk-1.0 libbamf3 xfixes gee-1.0 plank gnome-desktop-3.0)
set (MUTTER36_FLAGS "")
pkg_check_modules(MUTTER36 QUIET libmutter>=3.5)
if (MUTTER36_FOUND)
pkg_check_modules(MUTTER36 REQUIRED libmutter>=3.6.3)
set (MUTTER36_FLAGS "--define=HAS_MUTTER36")
endif (MUTTER36_FOUND)
set (MUTTER38_FLAGS "")
pkg_check_modules(MUTTER38 QUIET libmutter>=3.7)
if (MUTTER38_FOUND)
pkg_check_modules(MUTTER38 REQUIRED libmutter>=3.8.4)
set (MUTTER38_FLAGS "--define=HAS_MUTTER38")
endif (MUTTER38_FOUND)
set (MUTTER310_FLAGS "")
pkg_check_modules(MUTTER310 QUIET libmutter>=3.9)
if (MUTTER310_FOUND)
pkg_check_modules(MUTTER310 REQUIRED libmutter>=3.10.3)
set (MUTTER310_FLAGS "--define=HAS_MUTTER310")
endif (MUTTER310_FOUND)
set (MUTTER312_FLAGS "")
pkg_check_modules(MUTTER312 QUIET libmutter>=3.11)
if (MUTTER312_FOUND)
pkg_check_modules(MUTTER310 REQUIRED libmutter>=3.11.5)
set (MUTTER312_FLAGS "--define=HAS_MUTTER312")
endif (MUTTER312_FOUND)
add_definitions(${DEPS_CFLAGS})
link_libraries(${DEPS_LIBRARIES})
link_directories(${DEPS_LIBRARY_DIRS})
find_package(Vala REQUIRED)
include(ValaVersion)
ensure_vala_version("0.16.1" MINIMUM)
include(ValaPrecompile)
vala_precompile(VALA_C
src/DBus.vala
src/DragDropAction.vala
src/Main.vala
src/Plugin.vala
src/ScreenSaver.vala
src/Settings.vala
src/TextShadowEffect.vala
src/Utils.vala
src/Zooming.vala
src/Background/Background.vala
src/Background/BackgroundCache.vala
src/Background/BackgroundManager.vala
src/Background/SlideShow.vala
src/Background/SystemBackground.vala
src/Widgets/AppIcon.vala
src/Widgets/WindowOverview.vala
src/Widgets/WindowSwitcher.vala
src/Widgets/WindowThumb.vala
src/Widgets/WorkspaceThumb.vala
src/Widgets/WorkspaceView.vala
src/Widgets/MultitaskingView/IconGroup.vala
src/Widgets/MultitaskingView/MultitaskingView.vala
src/Widgets/MultitaskingView/Workspace.vala
${CMAKE_BINARY_DIR}/src/Config.vala
PACKAGES
granite
libbamf3
libmutter
plank
clutter-gtk-1.0
gdk-x11-3.0
gdesktopenums-3.0
gnome-desktop-3.0
xfixes-4.0
OPTIONS
-g
--enable-deprecated
--vapidir=${CMAKE_CURRENT_SOURCE_DIR}/vapi/
${MUTTER36_FLAGS}
${MUTTER38_FLAGS}
${MUTTER310_FLAGS}
${MUTTER312_FLAGS}
)
#add_subdirectory (po)
include(GSettings)
add_schema ("data/org.pantheon.desktop.gala.gschema.xml")
add_executable(gala ${VALA_C})#src/main.c)
target_link_libraries(gala m)
install(TARGETS gala RUNTIME DESTINATION bin)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/gala.desktop DESTINATION share/applications)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/gala.css DESTINATION ${PKGDATADIR})
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/texture.png DESTINATION ${PKGDATADIR})

674
COPYING Normal file
View File

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

388
INSTALL
View File

@ -1,18 +1,370 @@
Dependencies:
cmake
libgranite-dev
libmutter-dev
libclutter-gtk-1.0-dev
libgtk-3-dev
gsettings-desktop-schemas-dev
libxfixes-dev
libbamf3-dev
valac-0.16
Installation:
bzr branch lp:gala
cd gala
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr
sudo make install
Installation Instructions
*************************
Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,
Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. This file is offered as-is,
without warranty of any kind.
Basic Installation
==================
Briefly, the shell command `./configure && make && make install'
should configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package. Some packages provide this
`INSTALL' file but do not implement all of the features documented
below. The lack of an optional feature in a given package is not
necessarily a bug. More recommendations for GNU packages can be found
in *note Makefile Conventions: (standards)Makefile Conventions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale
cache files.
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You need `configure.ac' if
you want to change it or regenerate `configure' using a newer version
of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system.
Running `configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package, generally using the just-built uninstalled binaries.
4. Type `make install' to install the programs and any data files and
documentation. When installing into a prefix owned by root, it is
recommended that the package be configured and built as a regular
user, and only the `make install' phase executed with root
privileges.
5. Optionally, type `make installcheck' to repeat any self-tests, but
this time using the binaries in their final installed location.
This target does not install anything. Running this target as a
regular user, particularly if the prior `make install' required
root privileges, verifies that the installation completed
correctly.
6. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
7. Often, you can also type `make uninstall' to remove the installed
files again. In practice, not all packages have tested that
uninstallation works correctly, even though it is required by the
GNU Coding Standards.
8. Some packages, particularly those that use Automake, provide `make
distcheck', which can by used by developers to test that all other
targets like `make install' and `make uninstall' work correctly.
This target is generally not run by end users.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. Run `./configure --help'
for details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you can use GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'. This
is known as a "VPATH" build.
With a non-GNU `make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use `make distclean' before
reconfiguring for another architecture.
On MacOS X 10.5 and later systems, you can create libraries and
executables that work on multiple system types--known as "fat" or
"universal" binaries--by specifying multiple `-arch' options to the
compiler but only a single `-arch' option to the preprocessor. Like
this:
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CPP="gcc -E" CXXCPP="g++ -E"
This is not guaranteed to produce working output in all cases, you
may have to build one architecture at a time and combine the results
using the `lipo' tool if you have problems.
Installation Names
==================
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX', where PREFIX must be an
absolute file name.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them. In general, the
default for these options is expressed in terms of `${prefix}', so that
specifying just `--prefix' will affect all of the other directory
specifications that were not explicitly provided.
The most portable way to affect installation locations is to pass the
correct locations to `configure'; however, many packages provide one or
both of the following shortcuts of passing variable assignments to the
`make install' command line to change installation locations without
having to reconfigure or recompile.
The first method involves providing an override variable for each
affected directory. For example, `make install
prefix=/alternate/directory' will choose an alternate location for all
directory configuration variables that were expressed in terms of
`${prefix}'. Any directories that were specified during `configure',
but not in terms of `${prefix}', must each be overridden at install
time for the entire installation to be relocated. The approach of
makefile variable overrides for each directory variable is required by
the GNU Coding Standards, and ideally causes no recompilation.
However, some platforms have known limitations with the semantics of
shared libraries that end up requiring recompilation when using this
method, particularly noticeable in packages that use GNU Libtool.
The second method involves providing the `DESTDIR' variable. For
example, `make install DESTDIR=/alternate/directory' will prepend
`/alternate/directory' before all installation names. The approach of
`DESTDIR' overrides is not required by the GNU Coding Standards, and
does not work on platforms that have drive letters. On the other hand,
it does better at avoiding recompilation issues, and works well even
when some directory options were not specified in terms of `${prefix}'
at `configure' time.
Optional Features
=================
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Some packages offer the ability to configure how verbose the
execution of `make' will be. For these packages, running `./configure
--enable-silent-rules' sets the default to minimal output, which can be
overridden with `make V=1'; while running `./configure
--disable-silent-rules' sets the default to verbose, which can be
overridden with `make V=0'.
Particular systems
==================
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
CC is not installed, it is recommended to use the following options in
order to use an ANSI C compiler:
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
HP-UX `make' updates targets which have the same time stamps as
their prerequisites, which makes it generally unusable when shipped
generated files such as `configure' are involved. Use GNU `make'
instead.
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
a workaround. If GNU CC is not installed, it is therefore recommended
to try
./configure CC="cc"
and if that doesn't work, try
./configure CC="cc -nodtk"
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
directory contains several dysfunctional programs; working variants of
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
in your `PATH', put it _after_ `/usr/bin'.
On Haiku, software installed for all users goes in `/boot/common',
not `/usr/local'. It is recommended to use the following options:
./configure --prefix=/boot/common
Specifying the System Type
==========================
There may be some features `configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, `configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS
KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf limitation. Until the limitation is lifted, you can use
this workaround:
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
======================
`configure' recognizes the following options to control how it
operates.
`--help'
`-h'
Print a summary of all of the options to `configure', and exit.
`--help=short'
`--help=recursive'
Print a summary of the options unique to this package's
`configure', and exit. The `short' variant lists options used
only in the top level, while the `recursive' variant lists options
also present in any nested packages.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--prefix=DIR'
Use DIR as the installation prefix. *note Installation Names::
for more details, including other options available for fine-tuning
the installation locations.
`--no-create'
`-n'
Run the configure checks, but stop before creating any output
files.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

47
Makefile.am Normal file
View File

@ -0,0 +1,47 @@
include $(top_srcdir)/Makefile.common
SUBDIRS = \
data \
lib \
plugins \
src \
po \
vapi \
$(NULL)
EXTRA_DIST = \
.version \
build-aux/bzr-version-gen \
$(NULL)
BUILT_SOURCES = \
$(top_srcdir)/.version \
$(NULL)
$(top_srcdir)/.version:
echo $(VERSION) > $@-t && mv $@-t $@
dist-hook:
echo $(VERSION) > $(distdir)/.tarball-version
distclean-local:
if test "x$(srcdir)" = "x."; then :; else \
rm -f ChangeLog; \
fi
ChangeLog:
@echo Creating $@
@if test -d "$(srcdir)/.bzr"; then \
(bzr log --gnu -n1) | fmt --split-only --width=80 > $@.tmp \
&& mv -f $@.tmp $@ \
|| ($(RM) $@.tmp; \
echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \
(test -f $@ || echo git-log is required to generate this file >> $@)); \
else \
test -f $@ || \
(echo A git checkout and git-log is required to generate ChangeLog >&2 && \
echo A git checkout and git-log is required to generate this file >> $@); \
fi
.PHONY: ChangeLog

15
Makefile.common Normal file
View File

@ -0,0 +1,15 @@
NULL =
AM_V_VALA = $(am__v_VALA_$(V))
am__v_VALA_ = $(am__v_VALA_$(AM_DEFAULT_VERBOSITY))
am__v_VALA_0 = @echo " VALAC " $?;
AM_CPPFLAGS = \
-include $(CONFIG_HEADER) \
-DDATADIR=\"$(datadir)\" \
-DPKGDATADIR=\"$(pkgdatadir)\" \
-DLIBDIR=\"$(libdir)\" \
-DPKGLIBDIR=\"$(pkglibdir)\" \
-DPLUGINDIR=\"$(pkglibdir)/plugins\" \
-DSCHEMA=\"org.pantheon.desktop.gala\" \
$(NULL)

0
NEWS Normal file
View File

0
README Normal file
View File

40
autogen.sh Executable file
View File

@ -0,0 +1,40 @@
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
PKG_NAME="gala"
(test -f $srcdir/configure.ac \
&& test -f $srcdir/autogen.sh) || {
echo -n "**Error**: Directory \`$srcdir' does not look like the"
echo " top-level $PKG_NAME directory"
exit 1
}
if which gnome-autogen.sh ; then
REQUIRED_AUTOMAKE_VERSION=1.11 . gnome-autogen.sh
else
if which intltoolize && which autoreconf ; then
intltoolize --copy --force --automake || \
(echo "There was an error in running intltoolize." > /dev/stderr;
exit 1)
autoreconf --force --install || \
(echo "There was an error in running autoreconf." > /dev/stderr;
exit 1)
else
echo "No build script available. You have two choices:"
echo "1. You need to install the gnome-common module and make"
echo " sure the gnome-autogen.sh script is in your \$PATH."
echo "2. You need to install the following scripts:"
echo " * intltool"
echo " * libtool"
echo " * automake"
echo " * autoconf"
echo " Additionally, you need to make"
echo " sure that they are in your \$PATH."
exit 1
fi
fi

62
build-aux/bzr-version-gen Executable file
View File

@ -0,0 +1,62 @@
#!/bin/sh
scriptversion=2010-05-09.22; # UTC
# Copyright (C) 2010, 2011 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Additional permission under GNU GPL version 3 section 7
# Written by Giuseppe Scrivano.
if test -f .tarball-version
then
cat .tarball-version | tr -d '\n'
exit 0
fi
DIRTY=""
test -n "$(bzr diff | tr -d '\n')" && DIRTY="-dirty"
REVNO=$(bzr revno)
TAG=$(bzr tags -r $REVNO | cut -d' ' -f1)
if test -z "$TAG"
then
TAG=$(bzr tags -r ..$REVNO | cut -d' ' -f1)
# No tags yet
if test -z "$1"
then
test -z "$TAG" && TAG="unknown"
else
TAG=$1
fi
TAG=$TAG.$REVNO
fi
printf "%s%s" "$TAG" "$DIRTY"
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@ -1,65 +0,0 @@
##
# Copyright 2009-2010 Jakob Westhoff. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY JAKOB WESTHOFF ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL JAKOB WESTHOFF OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and documentation are those
# of the authors and should not be interpreted as representing official policies,
# either expressed or implied, of Jakob Westhoff
##
##
# Find module for the Vala compiler (valac)
#
# This module determines wheter a Vala compiler is installed on the current
# system and where its executable is.
#
# Call the module using "find_package(Vala) from within your CMakeLists.txt.
#
# The following variables will be set after an invocation:
#
# VALA_FOUND Whether the vala compiler has been found or not
# VALA_EXECUTABLE Full path to the valac executable if it has been found
# VALA_VERSION Version number of the available valac
##
# Search for the valac executable in the usual system paths.
find_program(VALA_EXECUTABLE
NAMES valac)
# Handle the QUIETLY and REQUIRED arguments, which may be given to the find call.
# Furthermore set VALA_FOUND to TRUE if Vala has been found (aka.
# VALA_EXECUTABLE is set)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Vala DEFAULT_MSG VALA_EXECUTABLE)
mark_as_advanced(VALA_EXECUTABLE)
# Determine the valac version
if(VALA_FOUND)
execute_process(COMMAND ${VALA_EXECUTABLE} "--version"
OUTPUT_VARIABLE "VALA_VERSION")
string(REPLACE "Vala" "" "VALA_VERSION" ${VALA_VERSION})
string(STRIP ${VALA_VERSION} "VALA_VERSION")
endif(VALA_FOUND)

View File

@ -1,42 +0,0 @@
# GSettings.cmake, CMake macros written for Marlin, feel free to re-use them.
option (GSETTINGS_LOCALINSTALL "Install GSettings Schemas locally instead of to the GLib prefix" ON)
option (GSETTINGS_COMPILE "Compile GSettings Schemas after installation" ${GSETTINGS_LOCALINSTALL})
if(GSETTINGS_LOCALINSTALL)
message(STATUS "GSettings schemas will be installed locally.")
endif()
if(GSETTINGS_COMPILE)
message(STATUS "GSettings shemas will be compiled.")
endif()
macro(add_schema SCHEMA_NAME)
set(PKG_CONFIG_EXECUTABLE pkg-config)
# Have an option to not install the schema into where GLib is
if (GSETTINGS_LOCALINSTALL)
SET (GSETTINGS_DIR "${CMAKE_INSTALL_PREFIX}/share/glib-2.0/schemas/")
else (GSETTINGS_LOCALINSTALL)
execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} glib-2.0 --variable prefix OUTPUT_VARIABLE _glib_prefix OUTPUT_STRIP_TRAILING_WHITESPACE)
SET (GSETTINGS_DIR "${_glib_prefix}/share/glib-2.0/schemas/")
endif (GSETTINGS_LOCALINSTALL)
# Run the validator and error if it fails
execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} gio-2.0 --variable glib_compile_schemas OUTPUT_VARIABLE _glib_comple_schemas OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process (COMMAND ${_glib_comple_schemas} --dry-run --schema-file=${CMAKE_CURRENT_SOURCE_DIR}/${SCHEMA_NAME} ERROR_VARIABLE _schemas_invalid OUTPUT_STRIP_TRAILING_WHITESPACE)
if (_schemas_invalid)
message (SEND_ERROR "Schema validation error: ${_schemas_invalid}")
endif (_schemas_invalid)
# Actually install and recomple schemas
message (STATUS "GSettings schemas will be installed into ${GSETTINGS_DIR}")
install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/${SCHEMA_NAME} DESTINATION ${GSETTINGS_DIR} OPTIONAL)
if (GSETTINGS_COMPILE)
install (CODE "message (STATUS \"Compiling GSettings schemas\")")
install (CODE "execute_process (COMMAND ${_glib_comple_schemas} ${GSETTINGS_DIR})")
endif ()
endmacro()

View File

@ -1,36 +0,0 @@
##
# This is a helper Macro to parse optional arguments in Macros/Functions
# It has been taken from the public CMake wiki.
# See http://www.cmake.org/Wiki/CMakeMacroParseArguments for documentation and
# licensing.
##
macro(parse_arguments prefix arg_names option_names)
set(DEFAULT_ARGS)
foreach(arg_name ${arg_names})
set(${prefix}_${arg_name})
endforeach(arg_name)
foreach(option ${option_names})
set(${prefix}_${option} FALSE)
endforeach(option)
set(current_arg_name DEFAULT_ARGS)
set(current_arg_list)
foreach(arg ${ARGN})
set(larg_names ${arg_names})
list(FIND larg_names "${arg}" is_arg_name)
if(is_arg_name GREATER -1)
set(${prefix}_${current_arg_name} ${current_arg_list})
set(current_arg_name ${arg})
set(current_arg_list)
else(is_arg_name GREATER -1)
set(loption_names ${option_names})
list(FIND loption_names "${arg}" is_option)
if(is_option GREATER -1)
set(${prefix}_${arg} TRUE)
else(is_option GREATER -1)
set(current_arg_list ${current_arg_list} ${arg})
endif(is_option GREATER -1)
endif(is_arg_name GREATER -1)
endforeach(arg)
set(${prefix}_${current_arg_name} ${current_arg_list})
endmacro(parse_arguments)

View File

@ -1,10 +0,0 @@
Elementary CMake modules
This is a set of CMake modules: Translations, GSettings, and Vala modules.
For all the Vala related modules see README.Vala.rst:
- ParseArguments.cmake
- ValaPrecompile.cmake
- ValaVersion.cmake
- FindVala.cmake

View File

@ -1,173 +0,0 @@
==========
Vala CMake
==========
:Author:
Jakob Westhoff
:Version:
Draft
Overview
========
Vala CMake is a collection of macros for the CMake_ build system to allow the
creation and management of projects developed using the Vala_ programming
language or its "Genie" flavor (less tested).
Installation
============
To use the Vala macros in your own project you need to copy the macro files to
an arbitrary folder in your projects directory and reference them in your
``CMakeLists.txt`` file.
Assuming the macros are stored under ``cmake/vala`` in your projects folder you
need to add the following information to your base ``CMakeLists.txt``::
list(APPEND CMAKE_MODULE_PATH
${CMAKE_SOURCE_DIR}/cmake/vala
)
After the new module path as been added you can simply include the provided
modules or use the provided find routines.
Finding Vala
============
The find module for vala works like any other Find module in CMake.
You can use it by simply calling the usual ``find_package`` function. Default
parameters like ``REQUIRED`` and ``QUIETLY`` are supported.
::
find_package(Vala REQUIRED)
After a successful call to the find_package function the following variables
will be set:
VALA_FOUND
Whether the vala compiler has been found or not
VALA_EXECUTABLE
Full path to the valac executable if it has been found
VALA_VERSION
Version number of the available valac
Precompiling Vala sources
=========================
CMake is mainly supposed to handle c or c++ based projects. Luckily every vala
program is translated into plain c code using the vala compiler, followed by
normal compilation of the generated c program using gcc.
The macro ``vala_precompile`` uses that fact to create c files from your .vala
sources for further CMake processing.
The first parameter provided is a variable, which will be filled with a list of
c files outputted by the vala compiler. This list can than be used in
conjunction with functions like ``add_executable`` or others to create the
necessary compile rules with CMake.
The initial variable is followed by a list of .vala files to be compiled.
Please take care to add every vala file belonging to the currently compiled
project or library as Vala will otherwise not be able to resolve all
dependencies.
The following sections may be specified afterwards to provide certain options
to the vala compiler:
PACKAGES
A list of vala packages/libraries to be used during the compile cycle. The
package names are exactly the same, as they would be passed to the valac
"--pkg=" option.
OPTIONS
A list of optional options to be passed to the valac executable. This can be
used to pass "--thread" for example to enable multi-threading support.
DIRECTORY
Specify the directory where the output source files will be stored. If
ommitted, the source files will be stored in CMAKE_CURRENT_BINARY_DIR.
CUSTOM_VAPIS
A list of custom vapi files to be included for compilation. This can be
useful to include freshly created vala libraries without having to install
them in the system.
GENERATE_VAPI
Pass all the needed flags to the compiler to create an internal vapi for
the compiled library. The provided name will be used for this and a
<provided_name>.vapi file will be created.
GENERATE_HEADER
Let the compiler generate a header file for the compiled code. There will
be a header file as well as an internal header file being generated called
<provided_name>.h and <provided_name>_internal.h
The following call is a simple example to the vala_precompile macro showing an
example to every of the optional sections::
vala_precompile(VALA_C
source1.vala
source2.vala
source3.vala
PACKAGES
gtk+-2.0
gio-1.0
posix
OPTIONS
--thread
CUSTOM_VAPIS
some_vapi.vapi
GENERATE_VAPI
myvapi
GENERATE_HEADER
myheader
)
Most important is the variable VALA_C which will contain all the generated c
file names after the call. The easiest way to use this information is to tell
CMake to create an executable out of it.
::
add_executable(myexecutable ${VALA_C})
Further reading
===============
The `Pdf Presenter Console`__ , which is a vala based project of mine, makes
heavy usage of the here described macros. To look at a real world example of
these macros the mentioned project is the right place to take a look. The svn
trunk of it can be found at::
svn://pureenergy.cc/pdf_presenter_console/trunk
__ http://westhoffswelt.de/projects/pdf_presenter_console.html
Acknowledgments
===============
Thanks go out to Florian Sowade, a fellow local PHP-Usergroupie, who helped me
a lot with the initial version of this macros and always answered my mostly
dumb CMake questions.
.. _CMake: http://cmake.org
.. _Vala: http://live.gnome.org/Vala
.. _Genie: http://live.gnome.org/Genie
..
Local Variables:
mode: rst
fill-column: 79
End:
vim: et syn=rst tw=79

View File

@ -1,5 +0,0 @@
# Test macros for Marlin, feel free to re-use them.
macro(add_test_executable EXE_NAME)
add_test(${EXE_NAME} gtester ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME})
endmacro()

View File

@ -1,41 +0,0 @@
# Translations.cmake, CMake macros written for Marlin, feel free to re-use them
macro(add_translations_directory NLS_PACKAGE)
add_custom_target (i18n ALL COMMENT “Building i18n messages.”)
find_program (MSGFMT_EXECUTABLE msgfmt)
file (GLOB PO_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.po)
foreach (PO_INPUT ${PO_FILES})
get_filename_component (PO_INPUT_BASE ${PO_INPUT} NAME_WE)
set (MO_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PO_INPUT_BASE}.mo)
add_custom_command (TARGET i18n COMMAND ${MSGFMT_EXECUTABLE} -o ${MO_OUTPUT} ${PO_INPUT})
install (FILES ${MO_OUTPUT} DESTINATION
share/locale/${PO_INPUT_BASE}/LC_MESSAGES
RENAME ${NLS_PACKAGE}.mo)
endforeach (PO_INPUT ${PO_FILES})
endmacro(add_translations_directory)
macro(add_translations_catalog NLS_PACKAGE)
add_custom_target (pot COMMENT “Building translation catalog.”)
find_program (XGETTEXT_EXECUTABLE xgettext)
set(C_SOURCE "")
foreach(FILES_INPUT ${ARGN})
file (GLOB SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/${FILES_INPUT}/*.c)
foreach(C_FILE ${SOURCE_FILES})
set(C_SOURCE ${C_SOURCE} ${C_FILE})
endforeach()
file (GLOB SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/${FILES_INPUT}/*.vala)
foreach(C_FILE ${SOURCE_FILES})
set(C_SOURCE ${C_SOURCE} ${C_FILE})
endforeach()
endforeach()
add_custom_command (TARGET pot COMMAND
${XGETTEXT_EXECUTABLE} -d ${NLS_PACKAGE} -o ${CMAKE_CURRENT_SOURCE_DIR}/${NLS_PACKAGE}.pot
${VALA_SOURCE} ${C_SOURCE} --keyword="_" --from-code=UTF-8
)
endmacro()

View File

@ -1,187 +0,0 @@
##
# Copyright 2009-2010 Jakob Westhoff. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY JAKOB WESTHOFF ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL JAKOB WESTHOFF OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and documentation are those
# of the authors and should not be interpreted as representing official policies,
# either expressed or implied, of Jakob Westhoff
##
include(ParseArguments)
find_package(Vala REQUIRED)
##
# Compile vala files to their c equivalents for further processing.
#
# The "vala_precompile" macro takes care of calling the valac executable on the
# given source to produce c files which can then be processed further using
# default cmake functions.
#
# The first parameter provided is a variable, which will be filled with a list
# of c files outputted by the vala compiler. This list can than be used in
# conjuction with functions like "add_executable" or others to create the
# neccessary compile rules with CMake.
#
# The initial variable is followed by a list of .vala files to be compiled.
# Please take care to add every vala file belonging to the currently compiled
# project or library as Vala will otherwise not be able to resolve all
# dependencies.
#
# The following sections may be specified afterwards to provide certain options
# to the vala compiler:
#
# PACKAGES
# A list of vala packages/libraries to be used during the compile cycle. The
# package names are exactly the same, as they would be passed to the valac
# "--pkg=" option.
#
# OPTIONS
# A list of optional options to be passed to the valac executable. This can be
# used to pass "--thread" for example to enable multi-threading support.
#
# CUSTOM_VAPIS
# A list of custom vapi files to be included for compilation. This can be
# useful to include freshly created vala libraries without having to install
# them in the system.
#
# GENERATE_VAPI
# Pass all the needed flags to the compiler to create an internal vapi for
# the compiled library. The provided name will be used for this and a
# <provided_name>.vapi file will be created.
#
# GENERATE_HEADER
# Let the compiler generate a header file for the compiled code. There will
# be a header file as well as an internal header file being generated called
# <provided_name>.h and <provided_name>_internal.h
#
# The following call is a simple example to the vala_precompile macro showing
# an example to every of the optional sections:
#
# vala_precompile(VALA_C
# source1.vala
# source2.vala
# source3.vala
# PACKAGES
# gtk+-2.0
# gio-1.0
# posix
# DIRECTORY
# gen
# OPTIONS
# --thread
# CUSTOM_VAPIS
# some_vapi.vapi
# GENERATE_VAPI
# myvapi
# GENERATE_HEADER
# myheader
# )
#
# Most important is the variable VALA_C which will contain all the generated c
# file names after the call.
##
macro(vala_precompile output)
parse_arguments(ARGS "PACKAGES;OPTIONS;DIRECTORY;GENERATE_HEADER;GENERATE_VAPI;CUSTOM_VAPIS" "" ${ARGN})
if(ARGS_DIRECTORY)
set(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${ARGS_DIRECTORY})
else(ARGS_DIRECTORY)
set(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
endif(ARGS_DIRECTORY)
include_directories(${DIRECTORY})
set(vala_pkg_opts "")
foreach(pkg ${ARGS_PACKAGES})
list(APPEND vala_pkg_opts "--pkg=${pkg}")
endforeach(pkg ${ARGS_PACKAGES})
set(in_files "")
set(out_files "")
set(${output} "")
foreach(src ${ARGS_DEFAULT_ARGS})
string(REPLACE ${CMAKE_CURRENT_SOURCE_DIR}/ "" src ${src})
string(REGEX MATCH "^/" IS_MATCHED ${src})
if(${IS_MATCHED} MATCHES "/")
list(APPEND in_files "${src}")
else()
list(APPEND in_files "${CMAKE_CURRENT_SOURCE_DIR}/${src}")
endif()
string(REPLACE ".vala" ".c" src ${src})
string(REPLACE ".gs" ".c" src ${src})
if(${IS_MATCHED} MATCHES "/")
get_filename_component(VALA_FILE_NAME ${src} NAME)
set(out_file "${CMAKE_CURRENT_BINARY_DIR}/${VALA_FILE_NAME}")
list(APPEND out_files "${CMAKE_CURRENT_BINARY_DIR}/${VALA_FILE_NAME}")
else()
set(out_file "${DIRECTORY}/${src}")
list(APPEND out_files "${DIRECTORY}/${src}")
endif()
list(APPEND ${output} ${out_file})
endforeach(src ${ARGS_DEFAULT_ARGS})
set(custom_vapi_arguments "")
if(ARGS_CUSTOM_VAPIS)
foreach(vapi ${ARGS_CUSTOM_VAPIS})
if(${vapi} MATCHES ${CMAKE_SOURCE_DIR} OR ${vapi} MATCHES ${CMAKE_BINARY_DIR})
list(APPEND custom_vapi_arguments ${vapi})
else (${vapi} MATCHES ${CMAKE_SOURCE_DIR} OR ${vapi} MATCHES ${CMAKE_BINARY_DIR})
list(APPEND custom_vapi_arguments ${CMAKE_CURRENT_SOURCE_DIR}/${vapi})
endif(${vapi} MATCHES ${CMAKE_SOURCE_DIR} OR ${vapi} MATCHES ${CMAKE_BINARY_DIR})
endforeach(vapi ${ARGS_CUSTOM_VAPIS})
endif(ARGS_CUSTOM_VAPIS)
set(vapi_arguments "")
if(ARGS_GENERATE_VAPI)
list(APPEND out_files "${DIRECTORY}/${ARGS_GENERATE_VAPI}.vapi")
set(vapi_arguments "--internal-vapi=${ARGS_GENERATE_VAPI}.vapi")
# Header and internal header is needed to generate internal vapi
if (NOT ARGS_GENERATE_HEADER)
set(ARGS_GENERATE_HEADER ${ARGS_GENERATE_VAPI})
endif(NOT ARGS_GENERATE_HEADER)
endif(ARGS_GENERATE_VAPI)
set(header_arguments "")
if(ARGS_GENERATE_HEADER)
list(APPEND out_files "${DIRECTORY}/${ARGS_GENERATE_HEADER}.h")
list(APPEND out_files "${DIRECTORY}/${ARGS_GENERATE_HEADER}_internal.h")
list(APPEND header_arguments "--header=${DIRECTORY}/${ARGS_GENERATE_HEADER}.h")
list(APPEND header_arguments "--internal-header=${DIRECTORY}/${ARGS_GENERATE_HEADER}_internal.h")
endif(ARGS_GENERATE_HEADER)
add_custom_command(OUTPUT ${out_files}
COMMAND
${VALA_EXECUTABLE}
ARGS
"-C"
${header_arguments}
${vapi_arguments}
"-b" ${CMAKE_CURRENT_SOURCE_DIR}
"-d" ${DIRECTORY}
${vala_pkg_opts}
${ARGS_OPTIONS}
${in_files}
${custom_vapi_arguments}
DEPENDS
${in_files}
${ARGS_CUSTOM_VAPIS}
)
endmacro(vala_precompile)

View File

@ -1,96 +0,0 @@
##
# Copyright 2009-2010 Jakob Westhoff. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY JAKOB WESTHOFF ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL JAKOB WESTHOFF OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and documentation are those
# of the authors and should not be interpreted as representing official policies,
# either expressed or implied, of Jakob Westhoff
##
include(ParseArguments)
find_package(Vala REQUIRED)
##
# Ensure a certain valac version is available
#
# The initial argument is the version to check for
#
# It may be followed by a optional parameter to specifiy a version range. The
# following options are valid:
#
# EXACT
# Vala needs to be available in the exact version given
#
# MINIMUM
# The provided version is the minimum version. Therefore Vala needs to be
# available in the given version or any higher version
#
# MAXIMUM
# The provided version is the maximum. Therefore Vala needs to be available
# in the given version or any version older than this
#
# If no option is specified the version will be treated as a minimal version.
##
macro(ensure_vala_version version)
parse_arguments(ARGS "" "MINIMUM;MAXIMUM;EXACT" ${ARGN})
set(compare_message "")
set(error_message "")
if(ARGS_MINIMUM)
set(compare_message "a minimum ")
set(error_message "or greater ")
elseif(ARGS_MAXIMUM)
set(compare_message "a maximum ")
set(error_message "or less ")
endif(ARGS_MINIMUM)
message(STATUS
"checking for ${compare_message}Vala version of ${version}"
)
unset(version_accepted)
# MINIMUM is the default if no option is specified
if(ARGS_EXACT)
if(${VALA_VERSION} VERSION_EQUAL ${version} )
set(version_accepted TRUE)
endif(${VALA_VERSION} VERSION_EQUAL ${version})
elseif(ARGS_MAXIMUM)
if(${VALA_VERSION} VERSION_LESS ${version} OR ${VALA_VERSION} VERSION_EQUAL ${version})
set(version_accepted TRUE)
endif(${VALA_VERSION} VERSION_LESS ${version} OR ${VALA_VERSION} VERSION_EQUAL ${version})
else(ARGS_MAXIMUM)
if(${VALA_VERSION} VERSION_GREATER ${version} OR ${VALA_VERSION} VERSION_EQUAL ${version})
set(version_accepted TRUE)
endif(${VALA_VERSION} VERSION_GREATER ${version} OR ${VALA_VERSION} VERSION_EQUAL ${version})
endif(ARGS_EXACT)
if (NOT version_accepted)
message(FATAL_ERROR
"Vala version ${version} ${error_message}is required."
)
endif(NOT version_accepted)
message(STATUS
" found Vala, version ${VALA_VERSION}"
)
endmacro(ensure_vala_version)

206
configure.ac Normal file
View File

@ -0,0 +1,206 @@
# If not 1, append revision to the version number and enable other development stuff
m4_define([gala_released], [0])
m4_define([gala_major_version], [0])
m4_define([gala_minor_version], [1])
m4_define([gala_micro_version], [0])
m4_define([gala_nano_version], [0])
# If library source has changed since last release, increment revision
# If interfaces have been removed or changed since last release,
# increment current and set revision to 0
# If interfaces have been added since last release, increment age
# If interfaces have been removed since last release, set age to 0
m4_define([gala_lt_current], [0])
m4_define([gala_lt_revision], [0])
m4_define([gala_lt_age], [0])
# Display the nano_version only if it's not '0'
m4_define([gala_base_version],
gala_major_version.gala_minor_version.gala_micro_version)
m4_define([gala_full_version],
[m4_if(gala_nano_version, [0],
gala_base_version, gala_base_version.gala_nano_version)])
# Extend version with bzr revision for non-release builds
m4_define([gala_version], m4_if(gala_released, [1],
[gala_full_version], [m4_esyscmd([build-aux/bzr-version-gen gala_full_version])]))
m4_define([gala_major_minor_version], gala_major_version.gala_minor_version)
m4_define([gala_module_version], gala_lt_current)
AC_INIT([gala], gala_version,
[https://bugs.launchpad.net/gala], [gala],
[https://launchpad.net/gala])
AC_DEFINE(RELEASE_NAME, "Window Manager.", Codename of this release)
AC_DEFINE(VERSION_INFO, m4_if(gala_released, [1], "Release", "Development"), Version info for package)
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AC_PREREQ([2.65])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_SRCDIR([Makefile.am])
AC_CONFIG_HEADERS(config.h)
AC_CONFIG_SRCDIR([configure.ac])
AM_INIT_AUTOMAKE([1.11 tar-ustar dist-xz no-dist-gzip -Wno-portability subdir-objects])
AM_MAINTAINER_MODE
AC_PROG_CC
AM_PROG_CC_C_O
AC_DISABLE_STATIC
LT_INIT
PKG_PROG_PKG_CONFIG([0.21])
GLIB_GSETTINGS
AC_SUBST([CFLAGS])
AC_SUBST([CPPFLAGS])
AC_SUBST([LDFLAGS])
LT_CURRENT=gala_lt_current
LT_REVISION=gala_lt_revision
LT_AGE=gala_lt_age
AC_SUBST([LT_CURRENT])
AC_SUBST([LT_REVISION])
AC_SUBST([LT_AGE])
GALA_MAJOR_MINOR_VERSION=gala_major_minor_version
AC_SUBST([GALA_MAJOR_MINOR_VERSION])
API_VERSION=0.2
AC_SUBST([API_VERSION])
# -----------------------------------------------------------
# Vala
# -----------------------------------------------------------
VALA_MIN_VERSION=0.22.0
AM_PROG_VALAC([$VALA_MIN_VERSION])
if test "x$VALAC" = "x"; then
AC_MSG_ERROR([Vala requested but valac >= $VALA_MIN_VERSION is not installed])
fi
AC_PATH_PROG([VAPIGEN], [vapigen], [])
if test "x$VAPIGEN" = "x"; then
AC_MSG_ERROR([Vala must be built with --enable-vapigen])
fi
# -----------------------------------------------------------
# Dependencies
# -----------------------------------------------------------
GTK_MIN_VERSION=3.4.0
GLIB_MIN_VERSION=2.32.0
PLANK_MIN_VERSION=0.3.0
MUTTER_MIN_VERSION=3.8.4
MUTTER_API="3.8"
GALA_CORE_PKGS="gobject-2.0 >= $GLIB_MIN_VERSION \
glib-2.0 >= $GLIB_MIN_VERSION \
gio-2.0 >= $GLIB_MIN_VERSION \
gio-unix-2.0 >= $GLIB_MIN_VERSION \
gmodule-2.0 \
gtk+-3.0 >= $GTK_MIN_VERSION \
gdk-x11-3.0 >= $GTK_MIN_VERSION \
libbamf3 \
clutter-gtk-1.0 \
granite \
libmutter >= $MUTTER_MIN_VERSION \
gee-0.8 \
gnome-desktop-3.0 \
plank >= $PLANK_MIN_VERSION"
GALA_CORE_VALA_PKGS="--pkg gio-unix-2.0 \
--pkg gmodule-2.0 \
--pkg gtk+-3.0 \
--pkg gdk-x11-3.0 \
--pkg libbamf3 \
--pkg libmutter \
--pkg clutter-gtk-1.0 \
--pkg granite \
--pkg gee-0.8 \
--pkg gdesktopenums-3.0 \
--pkg gnome-desktop-3.0 \
--pkg xfixes-4.0 \
--pkg plank"
VALAFLAGS="$VALAFLAGS --thread --target-glib=2.32"
PKG_CHECK_MODULES(GALA_CORE, $GALA_CORE_PKGS)
# Plugins
PLUGIN_LDFLAGS="-module -avoid-version"
AC_SUBST([PLUGIN_LDFLAGS])
# -----------------------------------------------------------
# Optional Dependencies
# -----------------------------------------------------------
# 3.10
PKG_CHECK_MODULES(MUTTER, [libmutter >= 3.9], [have_mutter310=yes], [have_mutter310=no])
if test "x$have_mutter310" = "xyes" ; then
PKG_CHECK_MODULES(MUTTER, "libmutter >= 3.10.4")
VALAFLAGS="$VALAFLAGS --define HAS_MUTTER310"
MUTTER_API="3.10"
fi
# 3.12
PKG_CHECK_MODULES(MUTTER, [libmutter >= 3.11], [have_mutter312=yes], [have_mutter312=no])
if test "x$have_mutter312" = "xyes" ; then
PKG_CHECK_MODULES(MUTTER, [libmutter >= 3.11.91])
VALAFLAGS="$VALAFLAGS --define HAS_MUTTER312"
MUTTER_API="3.12"
fi
# -----------------------------------------------------------
# Addional configure flags
# -----------------------------------------------------------
# Enable Vala debug-flag by default for non-release builds
AC_ARG_ENABLE([debug],
AS_HELP_STRING([--disable-debug],[compile without debug code]),
[enable_debug=$enableval], [m4_if(gala_released, [1], [enable_debug=no], [enable_debug=yes])])
if test "x$enable_debug" = "xyes" ; then
VALAFLAGS="$VALAFLAGS -g"
fi
GALA_CORE_VALAFLAGS="$VALAFLAGS $GALA_CORE_VALA_PKGS"
AC_SUBST(GALA_CORE_VALAFLAGS)
# -----------------------------------------------------------
# Gettext
# -----------------------------------------------------------
GETTEXT_PACKAGE=AC_PACKAGE_NAME
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, ["$GETTEXT_PACKAGE"], [Define the gettext package to be used])
IT_PROG_INTLTOOL([0.35.0])
# -----------------------------------------------------------
# Final output
# -----------------------------------------------------------
AC_CONFIG_FILES([
Makefile
src/Makefile
lib/Makefile
data/Makefile
vapi/Makefile
plugins/Makefile
plugins/zoom/Makefile
po/Makefile.in
])
AC_OUTPUT
echo "
${PACKAGE} ${VERSION}
Prefix......................: ${prefix}
Vala Compiler...............: ${VALAC}
Vala Flags..................: ${VALAFLAGS}
C Compiler Flags............: ${CFLAGS}
Using Mutter................: ${MUTTER_API}
"

36
data/Makefile.am Normal file
View File

@ -0,0 +1,36 @@
stylesdir = $(pkgdatadir)
styles_DATA = gala.css texture.png
applicationsdir = $(datadir)/applications
applications_DATA = gala.desktop
gsettings_SCHEMAS = org.pantheon.desktop.gala.gschema.xml
%.gschema.xml.in: %.gschema.xml.in.in Makefile
$(AM_V_GEN) sed -e 's|@GETTEXT_PACKAGE[@]|$(GETTEXT_PACKAGE)|g' $< > $@ || rm $@
@INTLTOOL_XML_RULE@
@GSETTINGS_RULES@
gschemas.compiled: Makefile $(gsettings_SCHEMAS:.xml=.valid)
$(AM_V_GEN) $(GLIB_COMPILE_SCHEMAS) --targetdir=$(builddir) $(builddir)
all-local: gschemas.compiled
EXTRA_DIST = \
gala.css \
gala.desktop \
texture.png \
org.pantheon.desktop.gala.gschema.xml.in.in \
$(NULL)
CLEANFILES = \
$(applications_DATA) \
$(styles_DATA) \
$(gsettings_SCHEMAS) \
gschemas.compiled \
data/org.pantheon.desktop.gala.gschema.xml \
data/org.pantheon.desktop.gala.gschema.xml.in \
$(NULL)

View File

@ -83,7 +83,7 @@
</key>
</schema>
<schema path="/org/pantheon/desktop/gala/keybindings/" id="org.pantheon.desktop.gala.keybindings" gettext-domain="gala">
<schema path="/org/pantheon/desktop/gala/keybindings/" id="org.pantheon.desktop.gala.keybindings" gettext-domain="@GETTEXT_PACKAGE@">
<key type="as" name="switch-to-workspace-first">
<default><![CDATA[['<Super>Home']]]></default>
<summary>Shortcut to move to first workspace</summary>

66
lib/Makefile.am Normal file
View File

@ -0,0 +1,66 @@
include $(top_srcdir)/Makefile.common
VAPIDIR = $(top_srcdir)/vapi
BUILT_SOURCES = \
libgala_la_vala.stamp \
$(NULL)
libgala_la_LTLIBRARIES = libgala.la
libgala_ladir = $(pkglibdir)
libgala_la_CFLAGS = \
$(GALA_CORE_CFLAGS) \
-include config.h \
-w \
$(NULL)
libgala_la_LDFLAGS = \
-avoid-version \
$(GALA_CORE_LDFLAGS) \
$(NULL)
libgala_la_VALAFLAGS = \
$(GALA_CORE_VALAFLAGS) \
--vapidir $(VAPIDIR) \
$(VAPIDIR)/config.vapi \
$(NULL)
libgala_la_LIBADD = \
$(GALA_CORE_LIBS) \
$(NULL)
libgala_la_VALASOURCES = \
Plugin.vala \
Utils.vala \
WindowManager.vala \
$(NULL)
nodist_libgala_la_SOURCES = \
$(BUILT_SOURCES) \
$(libgala_la_VALASOURCES:.vala=.c) \
$(NULL)
libgala_la_vala.stamp: $(libgala_la_VALASOURCES)
$(AM_V_VALA)$(VALAC) \
$(libgala_la_VALAFLAGS) \
--basedir $(srcdir) \
--directory $(builddir) \
-C \
-H gala.h \
--vapi gala.vapi \
--library gala \
$(filter %.vala %.c,$^)
$(AM_V_at)touch $@
CLEANFILES = \
$(nodist_libgala_la_SOURCES) \
gala.vapi \
gala.h \
$(NULL)
EXTRA_DIST = \
$(libgala_la_VALASOURCES) \
$(NULL)

210
lib/Plugin.vala Normal file
View File

@ -0,0 +1,210 @@
//
// Copyright (C) 2014 Tom Beckmann
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
namespace Gala
{
public enum PluginFunction
{
ADDITION,
WINDOW_SWITCHER,
DESKTOP,
WORKSPACE_VIEW,
WINDOW_OVERVIEW
}
public enum LoadPriority
{
/**
* Have your plugin loaded immediately once gala has started
*/
IMMEDIATE,
/**
* Allow gala to defer loading your plugin once it got the
* major part of the initialization done
*/
DEFERRED
}
public struct PluginInfo
{
string name;
string author;
/**
* Type of your plugin class, has to be derived from the Plugin class.
*/
Type plugin_type;
/**
* This property allows you to override default functionality of gala
* so systems won't be instantiated next to each other. Use
* PluginFunction.ADDITION if no special component is overridden.
*/
PluginFunction provides;
/**
* Give gala a hint for when to load your plugin. Especially use DEFERRED
* if you're adding a completely new ui component that's not directly
* related to the wm.
*/
LoadPriority load_priority;
/**
* You don't have to fill this field, it will be filled by gala with
* the filename in which your module was found.
*/
string module_name;
}
/**
* This class has to be implemented by every plugin.
* Additionally, the plugin module is required to have a register_plugin
* function which returns a PluginInfo struct.
* The plugin_type field has to be the type of your plugin class derived
* from this class.
*/
public abstract class Plugin : Object
{
/**
* Emitted when update_region is called. Mainly for internal purposes.
*/
public signal void region_changed ();
/**
* The region indicates an area where mouse events should be sent to
* the stage, which means your actors, instead of the windows.
*
* It is calculated by the system whenever update_region is called.
* You can influce it with the custom_region and the track_actor function.
*/
public X.Xrectangle[] region { get; set; }
/**
* This list will be merged with the region property. See region for
* more details. Changing this property will cause update_region to be
* called. Default to null.
*/
protected X.Xrectangle[]? custom_region {
get {
return _custom_region;
}
protected set {
_custom_region = value;
update_region ();
}
}
/**
* Set this property to true while animating an actor if you have tracked
* actors to prevent constant recalculations of the regions during an
* animation.
*/
protected bool freeze_track { get; protected set; default = false; }
private X.Xrectangle[]? _custom_region = null;
private Gee.LinkedList<Clutter.Actor> tracked_actors = new Gee.LinkedList<Clutter.Actor> ();
/**
* Once this method is called you can start adding actors to the stage
* using via the windowmanager instance that is given to you.
*
* @param wm The window manager.
*/
public abstract void initialize (WindowManager wm);
/**
* This method is currently not called in the code, however you should
* still implement it to be compatible whenever we decide to use it.
* It should make sure that everything your plugin added to the stage
* is cleaned up.
*/
public abstract void destroy ();
/**
* Listen to changes to the allocation of actor and update the region
* accordingly. You may add multiple actors, their shapes will be
* combined when one of them changes.
*
* @param actor The actor to be tracked
*/
public void track_actor (Clutter.Actor actor)
{
tracked_actors.add (actor);
actor.allocation_changed.connect (actor_allocation_changed);
update_region ();
}
/**
* Stop listening to allocation changes and remove the actor's
* allocation from the region array.
*
* @param actor The actor to stop listening the changes on
*/
public void untrack_actor (Clutter.Actor actor)
{
if (tracked_actors.remove (actor)) {
actor.allocation_changed.disconnect (actor_allocation_changed);
}
}
/**
* You can call this method to force the system to update the region that
* is used by the window manager. It will automatically upon changes to
* the custom_region property and when a tracked actor's allocation changes
* unless freeze_track is set to true. You may need to call this function
* after setting freeze_track back to false after an animation to make the
* wm aware of the new position of the actor in question.
*/
public void update_region ()
{
var has_custom = custom_region != null;
var len = tracked_actors.size + (has_custom ? custom_region.length : 0);
X.Xrectangle[] regions = new X.Xrectangle[len];
var i = 0;
if (has_custom) {
for (var j = 0; j < custom_region.length; j++) {
regions[i++] = custom_region[j];
}
}
foreach (var actor in tracked_actors) {
float x, y, w, h;
actor.get_transformed_position (out x, out y);
actor.get_transformed_size (out w, out h);
if (w == 0 || h == 0)
continue;
regions[i++] = { (short)x, (short)y, (short)w, (short)h };
}
region = regions;
region_changed ();
}
private void actor_allocation_changed (Clutter.ActorBox box, Clutter.AllocationFlags f)
{
if (!freeze_track)
update_region ();
}
}
}

View File

@ -1,73 +1,35 @@
//
//
// Copyright (C) 2012 Tom Beckmann, Rico Tzschichholz
//
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
using Meta;
using Gala;
//
namespace Gala
{
public class Utils
{
/*
* Reload shadow settings
*/
public static void reload_shadow ()
{
var factory = ShadowFactory.get_default ();
var settings = ShadowSettings.get_default ();
Meta.ShadowParams shadow;
//normal focused
shadow = settings.get_shadowparams ("normal_focused");
factory.set_params ("normal", true, shadow);
//normal unfocused
shadow = settings.get_shadowparams ("normal_unfocused");
factory.set_params ("normal", false, shadow);
//menus
shadow = settings.get_shadowparams ("menu");
factory.set_params ("menu", false, shadow);
factory.set_params ("dropdown-menu", false, shadow);
factory.set_params ("popup-menu", false, shadow);
//dialog focused
shadow = settings.get_shadowparams ("dialog_focused");
factory.set_params ("dialog", true, shadow);
factory.set_params ("modal_dialog", false, shadow);
//dialog unfocused
shadow = settings.get_shadowparams ("normal_unfocused");
factory.set_params ("dialog", false, shadow);
factory.set_params ("modal_dialog", false, shadow);
}
// Cache xid:pixbuf and icon:pixbuf pairs to provide a faster way aquiring icons
static Gee.HashMap<string, Gdk.Pixbuf> xid_pixbuf_cache;
static Gee.HashMap<string, Gdk.Pixbuf> icon_pixbuf_cache;
static uint cache_clear_timeout = 0;
static construct
{
xid_pixbuf_cache = new Gee.HashMap<string, Gdk.Pixbuf> ();
icon_pixbuf_cache = new Gee.HashMap<string, Gdk.Pixbuf> ();
}
/**
* Clean icon caches
*/
@ -91,12 +53,12 @@ namespace Gala
}
}
}
public static void request_clean_icon_cache (uint32[] xids)
{
if (cache_clear_timeout > 0)
GLib.Source.remove (cache_clear_timeout);
cache_clear_timeout = Timeout.add_seconds (30, () => {
cache_clear_timeout = 0;
Idle.add (() => {
@ -106,28 +68,28 @@ namespace Gala
return false;
});
}
/**
* returns a pixbuf for the application of this window or a default icon
**/
public static Gdk.Pixbuf get_icon_for_window (Window window, int size)
public static Gdk.Pixbuf get_icon_for_window (Meta.Window window, int size)
{
Gdk.Pixbuf? result = null;
var xid = (uint32)window.get_xwindow ();
var xid_key = "%u::%i".printf (xid, size);
if ((result = xid_pixbuf_cache.get (xid_key)) != null)
return result;
var app = Bamf.Matcher.get_default ().get_application_for_xid (xid);
result = get_icon_for_application (app, size);
xid_pixbuf_cache.set (xid_key, result);
return result;
}
/**
* returns a pixbuf for this application or a default icon
**/
@ -135,10 +97,10 @@ namespace Gala
{
Gdk.Pixbuf? image = null;
bool not_cached = false;
string? icon = null;
string? icon_key = null;
if (app != null && app.get_desktop_file () != null) {
try {
var appinfo = new DesktopAppInfo.from_filename (app.get_desktop_file ());
@ -154,7 +116,7 @@ namespace Gala
warning (e.message);
}
}
if (image == null) {
try {
unowned Gtk.IconTheme icon_theme = Gtk.IconTheme.get_default ();
@ -168,7 +130,7 @@ namespace Gala
warning (e.message);
}
}
if (image == null) {
icon = "";
icon_key = "::%i".printf (size);
@ -178,96 +140,53 @@ namespace Gala
not_cached = true;
}
}
if (size != image.width || size != image.height)
image = Plank.Drawing.DrawingService.ar_scale (image, size, size);
if (not_cached)
icon_pixbuf_cache.set (icon_key, image);
return image;
}
/**
* get the next window that should be active on a workspace right now
**/
public static Window get_next_window (Meta.Workspace workspace, bool backward=false)
public static Meta.Window get_next_window (Meta.Workspace workspace, bool backward=false)
{
var screen = workspace.get_screen ();
var display = screen.get_display ();
var window = display.get_tab_next (Meta.TabList.NORMAL, screen,
var window = display.get_tab_next (Meta.TabList.NORMAL, screen,
screen.get_active_workspace (), null, backward);
if (window == null)
window = display.get_tab_current (Meta.TabList.NORMAL, screen, workspace);
return window;
}
/**
* set the area where clutter can receive events
**/
public static void set_input_area (Screen screen, InputArea area)
{
var display = screen.get_display ();
X.Xrectangle[] rects = {};
int width, height;
screen.get_size (out width, out height);
var geometry = screen.get_monitor_geometry (screen.get_primary_monitor ());
switch (area) {
case InputArea.FULLSCREEN:
X.Xrectangle rect = {0, 0, (ushort)width, (ushort)height};
rects = {rect};
break;
case InputArea.HOT_CORNER:
var schema = BehaviorSettings.get_default ().schema;
// if ActionType is NONE make it 0 sized
ushort tl_size = (schema.get_enum ("hotcorner-topleft") != ActionType.NONE ? 1 : 0);
ushort tr_size = (schema.get_enum ("hotcorner-topright") != ActionType.NONE ? 1 : 0);
ushort bl_size = (schema.get_enum ("hotcorner-bottomleft") != ActionType.NONE ? 1 : 0);
ushort br_size = (schema.get_enum ("hotcorner-bottomright") != ActionType.NONE ? 1 : 0);
X.Xrectangle topleft = {(short)geometry.x, (short)geometry.y, tl_size, tl_size};
X.Xrectangle topright = {(short)(geometry.x + geometry.width - 1), (short)geometry.y, tr_size, tr_size};
X.Xrectangle bottomleft = {(short)geometry.x, (short)(geometry.y + geometry.height - 1), bl_size, bl_size};
X.Xrectangle bottomright = {(short)(geometry.x + geometry.width - 1), (short)(geometry.y + geometry.height - 1), br_size, br_size};
rects = {topleft, topright, bottomleft, bottomright};
break;
case InputArea.NONE:
default:
Util.empty_stage_input_region (screen);
return;
}
var xregion = X.Fixes.create_region (display.get_xdisplay (), rects);
Util.set_stage_input_region (screen, xregion);
}
/**
* get the number of toplevel windows on a workspace
**/
public static uint get_n_windows (Workspace workspace)
public static uint get_n_windows (Meta.Workspace workspace)
{
var n = 0;
foreach (var window in workspace.list_windows ()) {
if (window.is_on_all_workspaces ())
continue;
if (window.window_type == WindowType.NORMAL ||
window.window_type == WindowType.DIALOG ||
window.window_type == WindowType.MODAL_DIALOG)
if (window.window_type == Meta.WindowType.NORMAL ||
window.window_type == Meta.WindowType.DIALOG ||
window.window_type == Meta.WindowType.MODAL_DIALOG)
n ++;
}
return n;
}
static Gtk.CssProvider fallback_style = null;
public static Gtk.CssProvider get_default_style ()
{
if (fallback_style == null) {
@ -276,11 +195,11 @@ namespace Gala
fallback_style.load_from_path (Config.PKGDATADIR + "/gala.css");
} catch (Error e) { warning (e.message); }
}
return fallback_style;
}
public static void get_window_frame_offset (Window window, out float x, out float y, out float width, out float height)
public static void get_window_frame_offset (Meta.Window window, out float x, out float y, out float width, out float height)
{
var actor = window.get_compositor_private () as Clutter.Actor;
var frame = window.get_outer_rect ();
@ -297,5 +216,53 @@ namespace Gala
else
screen.get_display ().get_compositor ().flash_screen (screen);
}
/**
* Plank DockTheme
*/
public class DockThemeManager : Object
{
Plank.DockPreferences? dock_settings = null;
Plank.Drawing.DockTheme? dock_theme = null;
public signal void dock_theme_changed (Plank.Drawing.DockTheme? old_theme,
Plank.Drawing.DockTheme new_theme);
DockThemeManager ()
{
dock_settings = new Plank.DockPreferences.with_filename (Environment.get_user_config_dir () + "/plank/dock1/settings");
dock_settings.notify["Theme"].connect (load_dock_theme);
}
public Plank.Drawing.DockTheme get_dock_theme ()
{
if (dock_theme == null)
load_dock_theme ();
return dock_theme;
}
public Plank.DockPreferences get_dock_settings ()
{
return dock_settings;
}
void load_dock_theme ()
{
var new_theme = new Plank.Drawing.DockTheme (dock_settings.Theme);
new_theme.load ("dock");
dock_theme_changed (dock_theme, new_theme);
dock_theme = new_theme;
}
static DockThemeManager? instance = null;
public static DockThemeManager get_default ()
{
if (instance == null)
instance = new DockThemeManager ();
return instance;
}
}
}
}

55
lib/WindowManager.vala Normal file
View File

@ -0,0 +1,55 @@
//
// Copyright (C) 2014 Tom Beckmann
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
namespace Gala
{
public enum ActionType
{
NONE = 0,
SHOW_WORKSPACE_VIEW,
MAXIMIZE_CURRENT,
MINIMIZE_CURRENT,
OPEN_LAUNCHER,
CUSTOM_COMMAND,
WINDOW_OVERVIEW,
WINDOW_OVERVIEW_ALL
}
public enum InputArea
{
NONE,
FULLSCREEN,
HOT_CORNER
}
public interface WindowManager : Meta.Plugin
{
public abstract Clutter.Actor ui_group { get; protected set; }
public abstract Clutter.Stage stage { get; protected set; }
public abstract Clutter.Actor window_group { get; protected set; }
public abstract Clutter.Actor top_window_group { get; protected set; }
public abstract Meta.BackgroundGroup background_group { get; protected set; }
public abstract void begin_modal ();
public abstract void end_modal ();
public abstract void perform_action (ActionType type);
public abstract void update_input_area ();
public abstract void move_window (Meta.Window? window, Meta.MotionDirection direction);
public abstract void switch_to_next_workspace (Meta.MotionDirection direction);
}
}

3
plugins/Makefile.am Normal file
View File

@ -0,0 +1,3 @@
SUBDIRS = \
zoom \
$(NULL)

118
plugins/template/Main.vala Normal file
View File

@ -0,0 +1,118 @@
//
// Copyright (C) 2014 Tom Beckmann
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
/*
This is a template class showing some of the things that can be done
with a gala plugin and how to do them.
*/
namespace Gala.Plugins.Template
{
public class Main : Gala.Plugin
{
const int PADDING = 50;
Gala.WindowManager? wm = null;
Clutter.Actor red_box;
// This function is called as soon as Gala has started and gives you
// an instance of the GalaWindowManager class.
public override void initialize (Gala.WindowManager wm)
{
// we will save the instance to our wm property so we can use it later again
// especially helpful when you have larger plugins with more functions,
// we won't need it here
this.wm = wm;
// for demonstration purposes we'll add a red quad to the stage which will
// turn green when clicked
red_box = new Clutter.Actor ();
red_box.set_size (100, 100);
red_box.background_color = { 255, 0, 0, 255 };
red_box.reactive = true;
red_box.button_press_event.connect (turn_green);
// we want to place it in the lower right of the primary monitor with a bit
// of padding. refer to vapi/libmutter.vapi in gala's source for something
// remotely similar to a documentation
var screen = wm.get_screen ();
var rect = screen.get_monitor_geometry (screen.get_primary_monitor ());
red_box.x = rect.x + rect.width - red_box.width - PADDING;
red_box.y = rect.y + rect.height - red_box.height - PADDING;
// to order Gala to deliver mouse events to our box instead of the underlying
// windows, we need to mark the region where the quad is located.
// The plugin class offers an utility function for this purpose, the track_actor
// function. It will update the region with the allocation of the actor
// whenever its allocation changes. Make sure to set freeze_track to
// true while animating the actor to not make gala update the region
// every single frame.
// You can also handle the region manually by setting the custom_region
// property. The tracked actors and custom regions will be merged by
// the plugin.
track_actor (red_box);
// now we'll add our box into the ui_group. This is where all the shell
// elements and also the windows and backgrouds are located.
wm.ui_group.add_child (red_box);
}
bool turn_green (Clutter.ButtonEvent event)
{
red_box.background_color = { 0, 255, 0, 255 };
return true;
}
// This function is actually not even called by Gala at the moment,
// still it might be a good idea to implement it anyway to make sure
// your plugin is compatible in case we'd add disabling specific plugins
// in the future
public override void destroy ()
{
// here you would destroy actors you added to the stage or remove
// keybindings
red_box.destroy ();
}
}
}
// this little function just tells Gala which class of those you may have in
// your plugin is the one you want to start with and delivers some additional
// details about your plugin. It also gives you the option to choose a specific
// function which your plugin fulfils. Gala will then make sure that there is
// no duplicate functionality.
public Gala.PluginInfo register_plugin ()
{
return {
"template-plugin", // the plugin's name
"Tom Beckmann <tomjonabc@gmail.com>", // you, the author
typeof (Gala.Plugins.Template.Main), // the type of your plugin class
Gala.PluginFunction.ADDITION, // the function which your plugin
// fulfils, ADDITION means nothing
// specific
Gala.LoadPriority.IMMEDIATE // indicates whether your plugin's
// start can be delayed until gala
// has loaded the important stuff or
// if you want your plugin to start
// right away. False means wait.
};
}

View File

@ -0,0 +1,58 @@
include $(top_srcdir)/Makefile.common
VAPIDIR = $(top_srcdir)/vapi
BUILT_SOURCES = libgala_template_la_vala.stamp
libgala_template_la_LTLIBRARIES = libgala-template.la
libgala_template_ladir = $(pkglibdir)/plugins
libgala_template_la_LDFLAGS = \
$(PLUGIN_LDFLAGS) \
$(GALA_CORE_LDFLAGS) \
$(top_builddir)/lib/libgala.la \
$(NULL)
libgala_template_la_CFLAGS = \
$(GALA_CORE_CFLAGS) \
-include config.h \
-w \
-I$(top_builddir)/lib \
$(NULL)
libgala_template_la_VALAFLAGS = \
$(GALA_CORE_VALAFLAGS) \
$(top_builddir)/lib/gala.vapi \
--vapidir $(VAPIDIR) \
$(VAPIDIR)/config.vapi \
$(NULL)
libgala_template_la_LIBADD = \
$(GALA_CORE_LIBS) \
$(NULL)
libgala_template_la_VALASOURCES = \
Main.vala \
$(NULL)
nodist_libgala_template_la_SOURCES = \
$(BUILT_SOURCES) \
$(libgala_template_la_VALASOURCES:.vala=.c) \
$(NULL)
libgala_template_la_vala.stamp: $(libgala_template_la_VALASOURCES)
$(AM_V_VALA)$(VALAC) \
$(libgala_template_la_VALAFLAGS) \
-C \
$(filter %.vala %.c,$^)
$(AM_V_at)touch $@
CLEANFILES = \
$(nodist_libgala_template_la_SOURCES) \
$(NULL)
EXTRA_DIST = \
$(libgala_template_la_VALASOURCES) \
$(NULL)

73
plugins/template/README Normal file
View File

@ -0,0 +1,73 @@
Note for compilition
--------------------
If you want your own plugin within this source tree
don't forget to add the new subdirectory to the plugins' Makefile.am
SUBDIRS list and add your Makefile to the list of Makefiles found at
about the end of the configure.ac file AC_CONFIG_FILES.
The API is currently internal until the API is finalized, so you have
to build it in this source tree.
Some more useful notes on developing plugins:
Modal Mode
----------
If you want to display large elements that can be toggled instead of small overlays,
you can use wm.begin_modal() to make Gala enter modal mode. In this mode, you'll be
able to receive key events and all mouse events will be delivered regardless of the
region you have set. Don't forget to call wm.end_modal() and provide an obvious way
to exit modal mode for the user, otherwise he will be stuck and can only restart
Gala.
Keybindings
-----------
To add keybindings, you'll need a gsettings schema. You can take a look at Gala's
schema in data/org.pantheon.desktop.gschema.xml for an example. You'll also find
how to correctly declare shortcut keys in that file. Once you got this file ready
it's pretty easy. Just enable its installation in cmake, the relevant is commented
out in this template, and call wm.get_screen().get_display().add_keybinding().
The keybinding function takes the name of the shortcut key in your
schema, then a GSettings instance for that schema, which can be obtained with
'new GLib.Settings("org.pantheon.gala.plugins.my-plugin")', then some flags, for
which you can almost always use 0, refer to the vapi for more details, and finally
your function as arguments. Its delegate is:
public delegate void KeyHandlerFunc (Meta.Display display, Meta.Screen screen,
Meta.Window? window, X.Event event, Meta.KeyBinding binding);
So it'd be something like
void initialize (Gala.WindowManager wm)
{
[...]
var display = wm.get_screen ().get_display ();
var schema = new GLib.Settings ("org.pantheon.desktop.gala.plugins");
display.add_keybinding ("my-shortcut", schema, 0, my_handler);
[...]
}
void my_handler (Meta.Display display, Meta.Screen screen, Meta.Window? window,
X.Event event, Meta.KeyBinding binding)
{
print ("Shortcut hit! D:");
}
void destroy ()
{
wm.get_screen ().get_display ().remove_keybinding ("my-shortcut");
}
Overriding default keybindings
------------------------------
Libmutter allows you to override exisiting shortcuts, which is a lot easier than
adding new ones. All you have to do is:
Keybinding.set_custom_handler ("shortcut-name", my_handler);
The signature for my_handler is the same as above.
More info
---------
A great source for exploring the possibilities of mutter's API is scrolling through
the mentioned mutter vapi. In some cases you can find documentation on particular
functions in the mutter source code. Just grep for their C names.
*/

View File

@ -1,53 +1,68 @@
//
// Copyright (C) 2012 Tom Beckmann, Rico Tzschichholz
//
//
// Copyright (C) 2013 Tom Beckmann, Rico Tzschichholz
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
using Clutter;
using Meta;
namespace Gala
namespace Gala.Plugins.Zoom
{
public class Zooming : Object
public class Main : Gala.Plugin
{
Plugin plugin;
const uint MOUSE_POLL_TIME = 50;
Gala.WindowManager? wm = null;
uint mouse_poll_timer = 0;
float current_zoom = 1.0f;
public Zooming (Plugin _plugin)
public override void initialize (Gala.WindowManager wm)
{
plugin = _plugin;
this.wm = wm;
var display = wm.get_screen ().get_display ();
var schema = new GLib.Settings (Config.SCHEMA + ".keybindings");
display.add_keybinding ("zoom-in", schema, 0, zoom_in);
display.add_keybinding ("zoom-out", schema, 0, zoom_out);
}
~Zooming ()
public override void destroy ()
{
if (wm == null)
return;
var display = wm.get_screen ().get_display ();
display.remove_keybinding ("zoom-in");
display.remove_keybinding ("zoom-out");
if (mouse_poll_timer > 0)
Source.remove (mouse_poll_timer);
mouse_poll_timer = 0;
}
public void zoom_in () {
void zoom_in (Meta.Display display, Meta.Screen screen,
Meta.Window? window, X.Event event, Meta.KeyBinding binding)
{
zoom (true);
}
public void zoom_out () {
void zoom_out (Meta.Display display, Meta.Screen screen,
Meta.Window? window, X.Event event, Meta.KeyBinding binding)
{
zoom (false);
}
void zoom (bool @in)
{
// Nothing to do if zooming out of our bounds is requested
@ -55,9 +70,9 @@ namespace Gala
return;
else if (current_zoom >= 2.5f && @in)
return;
var wins = Compositor.get_window_group_for_screen (plugin.get_screen ());
var wins = wm.ui_group;
// Add timer to poll current mouse position to reposition window-group
// to show requested zoomed area
if (mouse_poll_timer == 0) {
@ -66,36 +81,48 @@ namespace Gala
client_pointer.get_position (null, out mx, out my);
wins.scale_center_x = mx;
wins.scale_center_y = my;
mouse_poll_timer = Clutter.Threads.Timeout.add (MOUSE_POLL_TIME, () => {
mouse_poll_timer = Timeout.add (MOUSE_POLL_TIME, () => {
client_pointer.get_position (null, out mx, out my);
if (wins.scale_center_x == mx && wins.scale_center_y == my)
return true;
wins.animate (AnimationMode.LINEAR, MOUSE_POLL_TIME, scale_center_x : mx, scale_center_y : my);
wins.animate (Clutter.AnimationMode.LINEAR, MOUSE_POLL_TIME, scale_center_x : mx, scale_center_y : my);
return true;
});
}
current_zoom += (@in ? 0.5f : -0.5f);
if (current_zoom <= 1.0f) {
current_zoom = 1.0f;
if (mouse_poll_timer > 0)
Source.remove (mouse_poll_timer);
mouse_poll_timer = 0;
wins.animate (AnimationMode.EASE_OUT_CUBIC, 300, scale_x : 1.0f, scale_y : 1.0f).completed.connect (() => {
wins.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 300, scale_x : 1.0f, scale_y : 1.0f).completed.connect (() => {
wins.scale_center_x = 0.0f;
wins.scale_center_y = 0.0f;
});
return;
}
wins.animate (AnimationMode.EASE_OUT_CUBIC, 300, scale_x : current_zoom, scale_y : current_zoom);
wins.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 300, scale_x : current_zoom, scale_y : current_zoom);
}
}
}
public Gala.PluginInfo register_plugin ()
{
return Gala.PluginInfo () {
name = "Zoom",
author = "Gala Developers",
plugin_type = typeof (Gala.Plugins.Zoom.Main),
provides = Gala.PluginFunction.ADDITION,
load_priority = Gala.LoadPriority.IMMEDIATE
};
}

58
plugins/zoom/Makefile.am Normal file
View File

@ -0,0 +1,58 @@
include $(top_srcdir)/Makefile.common
VAPIDIR = $(top_srcdir)/vapi
BUILT_SOURCES = libgala_zoom_la_vala.stamp
libgala_zoom_la_LTLIBRARIES = libgala-zoom.la
libgala_zoom_ladir = $(pkglibdir)/plugins
libgala_zoom_la_LDFLAGS = \
$(PLUGIN_LDFLAGS) \
$(GALA_CORE_LDFLAGS) \
$(top_builddir)/lib/libgala.la \
$(NULL)
libgala_zoom_la_CFLAGS = \
$(GALA_CORE_CFLAGS) \
-include config.h \
-w \
-I$(top_builddir)/lib \
$(NULL)
libgala_zoom_la_VALAFLAGS = \
$(GALA_CORE_VALAFLAGS) \
$(top_builddir)/lib/gala.vapi \
--vapidir $(VAPIDIR) \
$(VAPIDIR)/config.vapi \
$(NULL)
libgala_zoom_la_LIBADD = \
$(GALA_CORE_LIBS) \
$(NULL)
libgala_zoom_la_VALASOURCES = \
Main.vala \
$(NULL)
nodist_libgala_zoom_la_SOURCES = \
$(BUILT_SOURCES) \
$(libgala_zoom_la_VALASOURCES:.vala=.c) \
$(NULL)
libgala_zoom_la_vala.stamp: $(libgala_zoom_la_VALASOURCES)
$(AM_V_VALA)$(VALAC) \
$(libgala_zoom_la_VALAFLAGS) \
-C \
$(filter %.vala %.c,$^)
$(AM_V_at)touch $@
CLEANFILES = \
$(nodist_libgala_zoom_la_SOURCES) \
$(NULL)
EXTRA_DIST = \
$(libgala_zoom_la_VALASOURCES) \
$(NULL)

View File

@ -1,5 +0,0 @@
include (Translations)
add_translations_directory ("agenda")
add_translations_catalog ("agenda"
../src
)

1
po/POTFILES.in Normal file
View File

@ -0,0 +1 @@
src/EndSessionDialog.vala

1
po/POTFILES.skip Normal file
View File

@ -0,0 +1 @@
src/EndSessionDialog.c

55
po/gala.pot Normal file
View File

@ -0,0 +1,55 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-04-08 09:38+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#. the restart type is currently used by the indicator for what is
#. labelled shutdown because of unity's implementation of it
#. apparently. So we got to adjust to that until they fix this.
#. logout
#: ../src/EndSessionDialog.vala:117
msgid "Are you sure you want to Log Out?"
msgstr ""
#: ../src/EndSessionDialog.vala:118
msgid "Log Out"
msgstr ""
#. shutdown
#. restart
#: ../src/EndSessionDialog.vala:123
msgid "Are you sure you want to Shut Down?"
msgstr ""
#: ../src/EndSessionDialog.vala:124
msgid "Shut Down"
msgstr ""
#: ../src/EndSessionDialog.vala:147
msgid "This will close any open app and turn off your device."
msgstr ""
#. the indicator does not have a separate item for restart, that's
#. why we show both shutdown and restart for the restart action
#. (which is sent for shutdown as described above)
#: ../src/EndSessionDialog.vala:153
msgid "Restart"
msgstr ""
#: ../src/EndSessionDialog.vala:160
msgid "Cancel"
msgstr ""

View File

@ -1,23 +1,22 @@
//
//
// Copyright (C) 2013 Tom Beckmann, Rico Tzschichholz
//
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
namespace Gala
{
#if HAS_MUTTER38
/**
* Group that holds a pattern at the very bottom and then an image showing the
* current wallpaper above (and one more additional image for transitions).
@ -27,6 +26,8 @@ namespace Gala
{
const uint ANIMATION_TRANSITION_DURATION = 1500;
public signal void changed ();
public Meta.Screen screen { get; construct; }
public int monitor { get; construct; }
public Settings settings { get; construct; }
@ -38,7 +39,7 @@ namespace Gala
{
Object (screen: screen, monitor: monitor, settings: settings);
}
construct
{
pattern = new Meta.BackgroundActor ();
@ -107,6 +108,8 @@ namespace Gala
if (all || key_changed == "picture-opacity") {
if (image != null)
image.opacity = (uint8)(settings.get_int ("picture-opacity") / 100.0 * 255);
changed ();
}
// update pattern
@ -118,6 +121,8 @@ namespace Gala
var secondary_color = Clutter.Color.from_string (settings.get_string ("secondary-color"));
var shading_type = shading_string_to_enum (settings.get_string ("color-shading-type"));
pattern.content = cache.load_pattern (monitor, primary_color, secondary_color, shading_type);
changed ();
}
}
@ -132,6 +137,8 @@ namespace Gala
image.animate (Clutter.AnimationMode.EASE_OUT_QUAD, ANIMATION_TRANSITION_DURATION,
opacity: 0).completed.connect (() => {
image.destroy ();
changed ();
});
return;
}
@ -146,6 +153,8 @@ namespace Gala
if (image != null)
image.destroy ();
image = new_image;
changed ();
});
}
@ -189,6 +198,5 @@ namespace Gala
return GDesktop.BackgroundStyle.NONE;
}
}
#endif
}

View File

@ -1,23 +1,22 @@
//
//
// Copyright (C) 2013 Tom Beckmann, Rico Tzschichholz
//
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
namespace Gala
{
#if HAS_MUTTER38
public class BackgroundCache : Object
{
struct WaitingCallback
@ -38,7 +37,7 @@ namespace Gala
{
return instance;
}
public Meta.Screen screen { get; construct; }
Gee.HashMap<string,Meta.Background> image_cache;
@ -49,7 +48,7 @@ namespace Gala
{
Object (screen: screen);
}
construct
{
image_cache = new Gee.HashMap<string,Meta.Background> ();
@ -114,6 +113,5 @@ namespace Gala
return content;
}
}
#endif
}

View File

@ -1,32 +1,32 @@
//
//
// Copyright (C) 2013 Tom Beckmann, Rico Tzschichholz
//
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
namespace Gala
{
#if HAS_MUTTER38
public class BackgroundManager : Meta.BackgroundGroup
{
public Meta.Screen screen { get; construct; }
public signal void changed ();
public BackgroundManager (Meta.Screen screen)
{
Object (screen: screen);
}
construct
{
screen.monitors_changed.connect (update);
@ -41,7 +41,13 @@ namespace Gala
void update ()
{
remove_all_children ();
var reference_child = get_child_at_index (0);
if (reference_child != null) {
(reference_child as Background).changed.disconnect (background_changed);
}
destroy_all_children ();
print ("DESTROYING!!!! \n");
var settings = BackgroundSettings.get_default ().schema;
@ -53,9 +59,16 @@ namespace Gala
background.set_size (geom.width, geom.height);
add_child (background);
if (i == 0)
background.changed.connect (background_changed);
}
}
void background_changed ()
{
changed ();
}
}
#endif
}

View File

@ -1,23 +1,22 @@
//
//
// Copyright (C) 2013 Tom Beckmann, Rico Tzschichholz
//
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
namespace Gala
{
#if HAS_MUTTER38
public class SlideShow : Meta.BackgroundGroup
{
const double ANIMATION_OPACITY_STEP_INCREMENT = 4.0;
@ -77,7 +76,7 @@ namespace Gala
} catch (Error e) {
warning (e.message);
}
return false;
}
@ -158,6 +157,5 @@ namespace Gala
queue_update_animation ();
}
}
#endif
}

View File

@ -1,30 +1,29 @@
//
//
// Copyright (C) 2013 Tom Beckmann, Rico Tzschichholz
//
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
namespace Gala
{
#if HAS_MUTTER38
public class SystemBackground : Meta.BackgroundActor
{
public SystemBackground ()
{
Object ();
}
construct
{
var cache = BackgroundCache.get_default ();
@ -34,6 +33,5 @@ namespace Gala
});
}
}
#endif
}

View File

@ -1,19 +1,19 @@
//
// Copyright (C) 2012 Tom Beckmann
//
//
// Copyright (C) 2012 - 2014 Tom Beckmann, Jacob Parker
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
namespace Gala
{
@ -21,18 +21,18 @@ namespace Gala
public class DBus
{
static DBus? instance;
static Plugin plugin;
static WindowManager wm;
[DBus (visibile = false)]
public static void init (Plugin _plugin)
public static void init (WindowManager _wm)
{
plugin = _plugin;
wm = _wm;
Bus.own_name (BusType.SESSION, "org.pantheon.gala", BusNameOwnerFlags.NONE,
(connection) => {
if (instance == null)
instance = new DBus ();
try {
connection.register_object ("/org/pantheon/gala", instance);
} catch (Error e) { warning (e.message); }
@ -40,14 +40,186 @@ namespace Gala
() => {},
() => warning ("Could not acquire name\n") );
}
private DBus ()
{
if (wm.background_group != null)
(wm.background_group as BackgroundManager).changed.connect (() => background_changed ());
else
assert_not_reached ();
}
public void perform_action (ActionType type)
{
plugin.perform_action (type);
wm.perform_action (type);
}
const double SATURATION_WEIGHT = 1.5;
const double WEIGHT_THRESHOLD = 1.0;
class DummyOffscreenEffect : Clutter.OffscreenEffect {
public signal void done_painting ();
public override void post_paint ()
{
base.post_paint ();
done_painting ();
}
}
public struct ColorInformation
{
double average_red;
double average_green;
double average_blue;
double mean;
double variance;
}
/**
* Emitted when the background change occured and the transition ended.
* You can safely call get_optimal_panel_alpha then. It is not guaranteed
* that this signal will be emitted only once per group of changes as often
* done by GUIs. The change may not be visible to the user.
*/
public signal void background_changed ();
/**
* Attaches a dummy offscreen effect to the background at monitor to get its
* isolated color data. Then calculate the red, green and blue components of
* the average color in that area and the mean color value and variance. All
* variables are returned as a tuple in that order.
*
* @param monitor The monitor where the panel will be placed
* @param reference_x X coordinate of the rectangle used to gather color data
* relative to the monitor you picked. Values will be clamped
* to its dimensions
* @param reference_y Y coordinate
* @param refenrece_width Width of the rectangle
* @param reference_height Height of the rectangle
*/
public async ColorInformation get_background_color_information (int monitor,
int reference_x, int reference_y, int reference_width, int reference_height)
throws DBusError
{
var background = wm.background_group.get_child_at_index (monitor);
if (background == null)
throw new DBusError.INVALID_ARGS ("Invalid monitor requested");
var effect = new DummyOffscreenEffect ();
background.add_effect (effect);
var tex_width = (int)background.width;
var tex_height = (int)background.height;
int x_start = reference_x;
int y_start = reference_y;
int width = int.min (tex_width - reference_x, reference_width);
int height = int.min (tex_height - reference_y, reference_height);
if (x_start > tex_width || x_start > tex_height || width <= 0 || height <= 0)
throw new DBusError.INVALID_ARGS ("Invalid rectangle specified");
double variance = 0, mean = 0,
rTotal = 0, gTotal = 0, bTotal = 0;
ulong paint_signal_handler = 0;
paint_signal_handler = effect.done_painting.connect (() => {
SignalHandler.disconnect (effect, paint_signal_handler);
background.remove_effect (effect);
var texture = (Cogl.Texture)effect.get_texture ();
var pixels = new uint8[texture.get_width () * texture.get_height () * 4];
var s = CoglFixes.texture_get_data (texture, Cogl.PixelFormat.BGRA_8888_PRE, 0, pixels);
int size = width * height;
double mean_squares = 0;
double pixel = 0;
double max, min, score, delta, scoreTotal = 0,
rTotal2 = 0, gTotal2 = 0, bTotal2 = 0;
// code to calculate weighted average color is copied from
// plank's lib/Drawing/DrawingService.vala average_color()
// http://bazaar.launchpad.net/~docky-core/plank/trunk/view/head:/lib/Drawing/DrawingService.vala
for (int y = y_start; y < height; y++) {
for (int x = x_start; x < width; x++) {
int i = y * width * 4 + x * 4;
uint8 r = pixels[i];
uint8 g = pixels[i + 1];
uint8 b = pixels[i + 2];
pixel = (0.3 * r + 0.6 * g + 0.11 * b) - 128f;
min = uint8.min (r, uint8.min (g, b));
max = uint8.max (r, uint8.max (g, b));
delta = max - min;
// prefer colored pixels over shades of grey
score = SATURATION_WEIGHT * (delta == 0 ? 0.0 : delta / max);
rTotal += score * r;
gTotal += score * g;
bTotal += score * b;
scoreTotal += score;
rTotal += r;
gTotal += g;
bTotal += b;
mean += pixel;
mean_squares += pixel * pixel;
}
}
scoreTotal /= size;
bTotal /= size;
gTotal /= size;
rTotal /= size;
if (scoreTotal > 0.0) {
bTotal /= scoreTotal;
gTotal /= scoreTotal;
rTotal /= scoreTotal;
}
bTotal2 /= size * uint8.MAX;
gTotal2 /= size * uint8.MAX;
rTotal2 /= size * uint8.MAX;
// combine weighted and not weighted sum depending on the average "saturation"
// if saturation isn't reasonable enough
// s = 0.0 -> f = 0.0 ; s = WEIGHT_THRESHOLD -> f = 1.0
if (scoreTotal <= WEIGHT_THRESHOLD) {
var f = 1.0 / WEIGHT_THRESHOLD * scoreTotal;
var rf = 1.0 - f;
bTotal = bTotal * f + bTotal2 * rf;
gTotal = gTotal * f + gTotal2 * rf;
rTotal = rTotal * f + rTotal2 * rf;
}
// there shouldn't be values larger then 1.0
var max_val = double.max (rTotal, double.max (gTotal, bTotal));
if (max_val > 1.0) {
bTotal /= max_val;
gTotal /= max_val;
rTotal /= max_val;
}
mean /= size;
mean_squares *= mean_squares / size;
variance = Math.sqrt (mean_squares - mean * mean) / (double) size;
get_background_color_information.callback ();
});
background.queue_redraw ();
yield;
return { rTotal, gTotal, bTotal, mean, variance };
}
}
}

View File

@ -1,19 +1,19 @@
//
//
// Copyright (C) 2013 Tom Beckmann
//
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
namespace Gala
{
@ -47,7 +47,7 @@ namespace Gala
/**
* A drag action has successfully been finished.
*
*
* @param actor The actor on which the drag finished
*/
public signal void drag_end (Clutter.Actor actor);
@ -63,7 +63,7 @@ namespace Gala
* Create a new DragDropAction
*
* @param type The type of this actor
* @param id An ID that marks which sources can be dragged on
* @param id An ID that marks which sources can be dragged on
* which destinations. It has to be the same for all actors that
* should be compatible with each other.
*/

270
src/EndSessionDialog.vala Normal file
View File

@ -0,0 +1,270 @@
//
// Copyright (C) 2014 Tom Beckmann
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// docs taken from unity indicator-session's
// src/backend-dbus/org.gnome.SessionManager.EndSessionDialog.xml
namespace Gala
{
enum EndSessionDialogType {
LOGOUT = 0,
SHUTDOWN = 1,
RESTART = 2
}
/**
* Private class wrapping most of the Gtk part of this dialog
*/
class Dialog : Gtk.Dialog
{
/**
* Confirm that logout has been clicked
*/
public signal void confirmed_logout ();
/**
* Confirm that reboot has been clicked
*/
public signal void confirmed_reboot ();
/**
* Confirm that shutdown has been clicked
*/
public signal void confirmed_shutdown ();
/**
* Type of the dialog. See constructor for more info.
*/
public EndSessionDialogType dialog_type { get; construct; }
/**
* Creates a new shutdown dialog
*
* @param type Set the type of this dialog. 0 creates a logout one,
* 1 creates a shutdown one and 2 will create a combined
* shutdown/reboot dialog.
*/
public Dialog (EndSessionDialogType type)
{
Object (type: Gtk.WindowType.POPUP, dialog_type: type);
}
construct
{
string icon_name, heading_text, button_text;
// the restart type is currently used by the indicator for what is
// labelled shutdown because of unity's implementation of it
// apparently. So we got to adjust to that until they fix this.
switch (dialog_type) {
case EndSessionDialogType.LOGOUT:
icon_name = "system-log-out";
heading_text = _("Are you sure you want to Log Out?");
button_text = _("Log Out");
break;
case EndSessionDialogType.SHUTDOWN:
case EndSessionDialogType.RESTART:
icon_name = "system-shutdown";
heading_text = _("Are you sure you want to Shut Down?");
button_text = _("Shut Down");
break;
/*case EndSessionDialogType.RESTART:
icon_name = "system-reboot";
heading_text = _("Are you sure you want to Restart?");
button_text = _("Restart");
break;*/
default:
warn_if_reached ();
break;
}
set_position (Gtk.WindowPosition.CENTER_ALWAYS);
var heading = new Gtk.Label ("<span weight='bold' size='larger'>" +
heading_text + "</span>");
heading.get_style_context ().add_class ("larger");
heading.use_markup = true;
heading.xalign = 0;
var grid = new Gtk.Grid ();
grid.column_spacing = 12;
grid.row_spacing = 12;
grid.margin_left = grid.margin_right = grid.margin_bottom = 12;
grid.attach (new Gtk.Image.from_icon_name (icon_name, Gtk.IconSize.DIALOG), 0, 0, 1, 2);
grid.attach (heading, 1, 0, 1, 1);
grid.attach (new Gtk.Label (_("This will close any open app and turn off your device.")), 1, 1, 1, 1);
// the indicator does not have a separate item for restart, that's
// why we show both shutdown and restart for the restart action
// (which is sent for shutdown as described above)
if (dialog_type == EndSessionDialogType.RESTART) {
var confirm_restart = add_button (_("Restart"), Gtk.ResponseType.OK) as Gtk.Button;
confirm_restart.clicked.connect (() => {
confirmed_reboot ();
destroy ();
});
}
var cancel = add_button (_("Cancel"), Gtk.ResponseType.CANCEL) as Gtk.Button;
cancel.clicked.connect (() => { destroy (); });
var confirm = add_button (button_text, Gtk.ResponseType.OK) as Gtk.Button;
confirm.get_style_context ().add_class ("destructive-action");
confirm.clicked.connect (() => {
if (dialog_type == EndSessionDialogType.RESTART
|| dialog_type == EndSessionDialogType.SHUTDOWN)
confirmed_shutdown ();
else
confirmed_logout ();
destroy ();
});
set_default (confirm);
get_content_area ().add (grid);
var action_area = get_action_area ();
action_area.margin_right = 6;
action_area.margin_bottom = 6;
}
public override void map ()
{
base.map ();
Gdk.pointer_grab (get_window (), true, Gdk.EventMask.BUTTON_PRESS_MASK
| Gdk.EventMask.BUTTON_RELEASE_MASK
| Gdk.EventMask.POINTER_MOTION_MASK,
null, null, 0);
Gdk.keyboard_grab (get_window (), true, 0);
}
public override void destroy ()
{
Gdk.pointer_ungrab (0);
Gdk.keyboard_ungrab (0);
base.destroy ();
}
}
[DBus (name = "org.gnome.SessionManager.EndSessionDialog")]
public class EndSessionDialog : Clutter.Actor
{
/**
* Owns the Unity DBus and registers an instance of the EndSessionDialog
*
* @param wm The window manager
*/
[DBus (visible = false)]
public static void register (WindowManager wm)
{
Bus.own_name (BusType.SESSION, "com.canonical.Unity",
BusNameOwnerFlags.REPLACE, (connection) => {
connection.register_object ("/org/gnome/SessionManager/EndSessionDialog",
new EndSessionDialog (wm));
},
() => { },
() => { warning ("Could not acquire Unity bus."); });
}
/**
* Confirm that logout has been clicked
*/
public signal void confirmed_logout ();
/**
* Confirm that reboot has been clicked
*/
public signal void confirmed_reboot ();
/**
* Confirm that shutdown has been clicked
*/
public signal void confirmed_shutdown ();
/**
* The dialog has been cancelled
*/
public signal void canceled ();
/**
* The dialog has been closed
*/
public signal void closed ();
[DBus (visible = false)]
public WindowManager wm { get; construct; }
public EndSessionDialog (WindowManager wm)
{
Object (wm: wm);
}
construct
{
background_color = { 0, 0, 0, 255 };
opacity = 0;
add_constraint (new Clutter.BindConstraint (wm.stage, Clutter.BindCoordinate.SIZE, 0));
}
/**
* This function opens a dialog which asks the user for confirmation
* a logout, poweroff or reboot action. The dialog has a timeout
* after which the action is automatically taken, and it should show
* the inhibitors to the user.
*
* @param type The type of dialog to show.
* 0 for logout, 1 for shutdown, 2 for restart.
* @param timestamp Timestamp of the user-initiated event which
* triggered the call, or 0 if the call was not
* triggered by an event.
* @param seconds_to_stay_open The number of seconds which the dialog should
* stay open before automatic action is taken.
* @param inhibitor_object_paths The object paths of all inhibitors that
* are registered for the action.
*/
public void open (uint type, uint timestamp, uint seconds_to_stay_open,
ObjectPath[] inhibitor_object_paths) throws IOError
{
// note on the implementation: the unity indicator currently does not use
// the seconds_to_stay_open and inhibitor_object_paths parameters, so we
// ignore them here for now as well.
if (type > 2)
throw new IOError.INVALID_ARGUMENT ("Invalid type requested");
wm.ui_group.insert_child_below (this, wm.top_window_group);
animate (Clutter.AnimationMode.EASE_OUT_QUAD, 600, opacity: 80);
var dialog = new Dialog ((EndSessionDialogType) type);
dialog.show_all ();
dialog.destroy.connect (() => {
animate (Clutter.AnimationMode.EASE_OUT_QUAD, 400, opacity: 0)
.completed.connect (() => { wm.ui_group.remove_child (this); });
closed ();
});
dialog.confirmed_logout.connect (() => { confirmed_logout (); });
dialog.confirmed_shutdown.connect (() => { confirmed_shutdown (); });
dialog.confirmed_reboot.connect (() => { confirmed_reboot (); });
}
}
}

110
src/InternalUtils.vala Normal file
View File

@ -0,0 +1,110 @@
//
// Copyright (C) 2012 Tom Beckmann, Rico Tzschichholz
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
using Meta;
using Gala;
namespace Gala
{
public class InternalUtils
{
/*
* Reload shadow settings
*/
public static void reload_shadow ()
{
var factory = ShadowFactory.get_default ();
var settings = ShadowSettings.get_default ();
Meta.ShadowParams shadow;
//normal focused
shadow = settings.get_shadowparams ("normal_focused");
factory.set_params ("normal", true, shadow);
//normal unfocused
shadow = settings.get_shadowparams ("normal_unfocused");
factory.set_params ("normal", false, shadow);
//menus
shadow = settings.get_shadowparams ("menu");
factory.set_params ("menu", false, shadow);
factory.set_params ("dropdown-menu", false, shadow);
factory.set_params ("popup-menu", false, shadow);
//dialog focused
shadow = settings.get_shadowparams ("dialog_focused");
factory.set_params ("dialog", true, shadow);
factory.set_params ("modal_dialog", false, shadow);
//dialog unfocused
shadow = settings.get_shadowparams ("normal_unfocused");
factory.set_params ("dialog", false, shadow);
factory.set_params ("modal_dialog", false, shadow);
}
/**
* set the area where clutter can receive events
**/
public static void set_input_area (Screen screen, InputArea area)
{
var display = screen.get_display ();
X.Xrectangle[] rects = {};
int width, height;
screen.get_size (out width, out height);
var geometry = screen.get_monitor_geometry (screen.get_primary_monitor ());
switch (area) {
case InputArea.FULLSCREEN:
X.Xrectangle rect = {0, 0, (ushort)width, (ushort)height};
rects = {rect};
break;
case InputArea.HOT_CORNER:
var schema = BehaviorSettings.get_default ().schema;
// if ActionType is NONE make it 0 sized
ushort tl_size = (schema.get_enum ("hotcorner-topleft") != ActionType.NONE ? 1 : 0);
ushort tr_size = (schema.get_enum ("hotcorner-topright") != ActionType.NONE ? 1 : 0);
ushort bl_size = (schema.get_enum ("hotcorner-bottomleft") != ActionType.NONE ? 1 : 0);
ushort br_size = (schema.get_enum ("hotcorner-bottomright") != ActionType.NONE ? 1 : 0);
X.Xrectangle topleft = {(short)geometry.x, (short)geometry.y, tl_size, tl_size};
X.Xrectangle topright = {(short)(geometry.x + geometry.width - 1), (short)geometry.y, tr_size, tr_size};
X.Xrectangle bottomleft = {(short)geometry.x, (short)(geometry.y + geometry.height - 1), bl_size, bl_size};
X.Xrectangle bottomright = {(short)(geometry.x + geometry.width - 1), (short)(geometry.y + geometry.height - 1), br_size, br_size};
rects = {topleft, topright, bottomleft, bottomright};
break;
case InputArea.NONE:
default:
Util.empty_stage_input_region (screen);
return;
}
// add plugin's requested areas
if (area == InputArea.FULLSCREEN || area == InputArea.HOT_CORNER) {
foreach (var rect in PluginManager.get_default ().regions) {
rects += rect;
}
}
var xregion = X.Fixes.create_region (display.get_xdisplay (), rects);
Util.set_stage_input_region (screen, xregion);
}
}
}

View File

@ -1,19 +1,19 @@
//
//
// Copyright (C) 2012 Tom Beckmann, Rico Tzschichholz
//
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
namespace Gala
{
@ -21,12 +21,12 @@ namespace Gala
{ "version", 0, OptionFlags.NO_ARG, OptionArg.CALLBACK, (void*) print_version, "Print version", null },
{ null }
};
void print_version () {
stdout.printf ("Gala %s\n", Config.VERSION);
Meta.exit (Meta.ExitCode.SUCCESS);
}
public static int main (string[] args)
{
unowned OptionContext ctx = Meta.get_option_context ();
@ -37,15 +37,11 @@ namespace Gala
stderr.printf ("Error initializing: %s\n", e.message);
Meta.exit (Meta.ExitCode.ERROR);
}
#if HAS_MUTTER36
Meta.Plugin.manager_set_plugin_type (new Plugin ().get_type ());
#else
Meta.Plugin.type_register (new Plugin ().get_type ());
#endif
Meta.Plugin.manager_set_plugin_type (new WindowManagerGala ().get_type ());
Meta.set_wm_name ("Mutter(Gala)");
/**
* Prevent Meta.init () from causing gtk to load gail and at-bridge
* Taken from Gnome-Shell main.c
@ -55,13 +51,13 @@ namespace Gala
Meta.init ();
GLib.Environment.unset_variable ("NO_GAIL");
GLib.Environment.unset_variable ("NO_AT_BRIDGE");
Plank.Services.Paths.initialize ("plank", Config.DATADIR + "/plank");
// Force initialization of static fields in Utils class
// https://bugzilla.gnome.org/show_bug.cgi?id=543189
typeof (Gala.Utils).class_ref ();
return Meta.run ();
}
}

81
src/Makefile.am Normal file
View File

@ -0,0 +1,81 @@
include $(top_srcdir)/Makefile.common
VAPIDIR = $(top_srcdir)/vapi
gala_VALAFLAGS = \
$(GALA_CORE_VALAFLAGS) \
$(top_builddir)/lib/gala.vapi \
--vapidir $(VAPIDIR) \
$(VAPIDIR)/config.vapi \
$(VAPIDIR)/cogl-fixes.vapi \
$(NULL)
galadir = $(bindir)
BUILT_SOURCES = gala_vala.stamp
gala_PROGRAMS = gala
gala_CFLAGS = \
$(GALA_CORE_CFLAGS) \
-include config.h \
-w \
-DGNOME_DESKTOP_USE_UNSTABLE_API \
-I$(top_builddir)/lib \
$(NULL)
gala_LDADD = \
-lm \
$(GALA_CORE_LIBS) \
$(top_builddir)/lib/libgala.la \
$(NULL)
gala_VALASOURCES = \
DBus.vala \
DragDropAction.vala \
EndSessionDialog.vala \
InternalUtils.vala \
Main.vala \
PluginManager.vala \
ScreenSaver.vala \
Settings.vala \
TextShadowEffect.vala \
WindowManager.vala \
Background/Background.vala \
Background/BackgroundCache.vala \
Background/BackgroundManager.vala \
Background/SlideShow.vala \
Background/SystemBackground.vala \
Widgets/AppIcon.vala \
Widgets/WindowOverview.vala \
Widgets/WindowSwitcher.vala \
Widgets/WindowThumb.vala \
Widgets/WorkspaceThumb.vala \
Widgets/WorkspaceView.vala \
Widgets/MultitaskingView/IconGroup.vala \
Widgets/MultitaskingView/MultitaskingView.vala \
Widgets/MultitaskingView/Workspace.vala \
$(NULL)
nodist_gala_SOURCES = \
gala_vala.stamp \
$(gala_VALASOURCES:.vala=.c) \
$(NULL)
gala_vala.stamp: $(gala_VALASOURCES)
$(AM_V_VALA)$(VALAC) \
$(gala_VALAFLAGS) \
--basedir $(srcdir) \
--directory $(builddir) \
-C \
$(filter %.vala %.c,$^)
$(AM_V_at)touch $@
CLEANFILES = \
$(nodist_gala_SOURCES) \
$(NULL)
EXTRA_DIST = \
$(gala_VALASOURCES) \
$(NULL)

220
src/PluginManager.vala Normal file
View File

@ -0,0 +1,220 @@
//
// Copyright (C) 2014 Tom Beckmann
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
namespace Gala
{
delegate PluginInfo RegisterPluginFunction ();
public class PluginManager : Object
{
static PluginManager? instance = null;
public static PluginManager get_default ()
{
if (instance == null)
instance = new PluginManager ();
return instance;
}
public signal void regions_changed ();
public bool initialized { get; private set; default = false; }
public X.Xrectangle[] regions { get; private set; }
public string? window_switcher_provider { get; private set; default = null; }
public string? desktop_provider { get; private set; default = null; }
public string? window_overview_provider { get; private set; default = null; }
public string? workspace_view_provider { get; private set; default = null; }
HashTable<string,Plugin> plugins;
File plugin_dir;
WindowManager? wm = null;
Gee.LinkedList<PluginInfo?> load_later_plugins;
PluginManager ()
{
plugins = new HashTable<string,Plugin> (str_hash, str_equal);
load_later_plugins = new Gee.LinkedList<PluginInfo?> ();
if (!Module.supported ()) {
warning ("Modules are not supported on this platform");
return;
}
plugin_dir = File.new_for_path (Config.PLUGINDIR);
if (!plugin_dir.query_exists ())
return;
try {
var enumerator = plugin_dir.enumerate_children (FileAttribute.STANDARD_NAME +
"," + FileAttribute.STANDARD_CONTENT_TYPE, 0);
FileInfo info;
while ((info = enumerator.next_file ()) != null) {
if (info.get_content_type () == "application/x-sharedlib")
load_module (info.get_name ());
}
} catch (Error e) {
warning (e.message);
}
try {
plugin_dir.monitor_directory (FileMonitorFlags.NONE, null).changed.connect ((file, other_file, type) => {
if (type == FileMonitorEvent.CREATED) {
load_module (file.get_basename ());
}
});
} catch (Error e) {
warning (e.message);
}
}
bool load_module (string plugin_name)
{
var path = Module.build_path (plugin_dir.get_path (), plugin_name);
var module = Module.open (path, ModuleFlags.BIND_LOCAL);
if (module == null) {
warning (Module.error ());
return false;
}
void* function;
module.symbol ("register_plugin", out function);
if (function == null) {
warning ("%s failed to register: register_plugin() function not found", plugin_name);
return false;
}
RegisterPluginFunction register = (RegisterPluginFunction)function;
var info = register ();
if (info.plugin_type.is_a (typeof (Plugin)) == false) {
warning ("%s does not return a class of type Plugin", plugin_name);
return false;
}
if (!check_provides (info.name, info.provides)) {
return false;
}
info.module_name = plugin_name;
module.make_resident ();
if (info.load_priority == LoadPriority.DEFERRED && !initialized) {
load_later_plugins.add (info);
} else {
load_plugin_class (info);
}
return true;
}
void load_plugin_class (PluginInfo info)
{
var plugin = (Plugin)Object.@new (info.plugin_type);
plugins.set (info.module_name, plugin);
debug ("Loaded plugin %s (%s)", info.name, info.module_name);
if (initialized) {
initialize_plugin (info.module_name, plugin);
recalculate_regions ();
}
}
void initialize_plugin (string plugin_name, Plugin plugin)
{
plugin.initialize (wm);
plugin.region_changed.connect (recalculate_regions);
}
bool check_provides (string name, PluginFunction provides)
{
var message = "Plugins %s and %s both provide %s functionality, using first one only";
switch (provides) {
case PluginFunction.WORKSPACE_VIEW:
if (workspace_view_provider != null) {
warning (message, workspace_view_provider, name, "workspace view");
return false;
}
workspace_view_provider = name;
return true;
case PluginFunction.WINDOW_OVERVIEW:
if (window_overview_provider != null) {
warning (message, window_overview_provider, name, "window overview");
return false;
}
window_overview_provider = name;
return true;
case PluginFunction.DESKTOP:
if (desktop_provider != null) {
warning (message, desktop_provider, name, "desktop");
return false;
}
desktop_provider = name;
return true;
case PluginFunction.WINDOW_SWITCHER:
if (window_switcher_provider != null) {
warning (message, window_switcher_provider, name, "window switcher");
return false;
}
window_switcher_provider = name;
return true;
}
return true;
}
public void initialize (WindowManager _wm)
{
wm = _wm;
plugins.@foreach (initialize_plugin);
recalculate_regions ();
initialized = true;
}
public void load_waiting_plugins ()
{
foreach (var info in load_later_plugins) {
load_plugin_class (info);
}
load_later_plugins.clear ();
}
/**
* Iterate over all plugins and grab their regions, update the regions
* array accordingly and emit the regions_changed signal.
*/
void recalculate_regions ()
{
X.Xrectangle[] regions = {};
plugins.@foreach ((name, plugin) => {
foreach (var region in plugin.region)
regions += region;
});
this.regions = regions;
regions_changed ();
}
}
}

View File

@ -1,19 +1,19 @@
//
//
// Copyright (C) 2012 Jaap Broekhuizen
//
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
namespace Gala
{

View File

@ -1,19 +1,19 @@
//
//
// Copyright (C) 2012 GardenGnome, Rico Tzschichholz, Tom Beckmann
//
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
namespace Gala
{
@ -26,70 +26,70 @@ namespace Gala
public string overlay_action { get; set; }
public string hotcorner_custom_command { get; set; }
public string[] dock_names { get; set; }
public WindowOverviewType window_overview_type { get; set; }
public ActionType hotcorner_topleft { get; set; }
public ActionType hotcorner_topright { get; set; }
public ActionType hotcorner_bottomleft { get; set; }
public ActionType hotcorner_bottomright { get; set; }
static BehaviorSettings? instance = null;
private BehaviorSettings ()
{
base (Config.SCHEMA + ".behavior");
}
public static BehaviorSettings get_default ()
{
if (instance == null)
instance = new BehaviorSettings ();
return instance;
}
}
public class KeybindingSettings : Granite.Services.Settings
{
static KeybindingSettings? instance = null;
private KeybindingSettings ()
{
base (Config.SCHEMA + ".keybindings");
}
public static KeybindingSettings get_default ()
{
if (instance == null)
instance = new KeybindingSettings ();
return instance;
}
}
public class AppearanceSettings : Granite.Services.Settings
{
public string button_layout { get; set; }
public bool attach_modal_dialogs { get; set; }
public bool dim_parents { get; set; }
static AppearanceSettings? instance = null;
private AppearanceSettings ()
{
base (Config.SCHEMA + ".appearance");
}
public static AppearanceSettings get_default ()
{
if (instance == null)
instance = new AppearanceSettings ();
return instance;
}
}
public class ShadowSettings : Granite.Services.Settings
{
public string[] menu { get; set; }
@ -97,35 +97,35 @@ namespace Gala
public string[] normal_unfocused { get; set; }
public string[] dialog_focused { get; set; }
public string[] dialog_unfocused { get; set; }
static ShadowSettings? instance = null;
private ShadowSettings ()
{
base (Config.SCHEMA + ".shadows");
}
public static ShadowSettings get_default ()
{
if (instance == null)
instance = new ShadowSettings ();
return instance;
}
public Meta.ShadowParams get_shadowparams (string class_name)
{
string[] val;
get (class_name, out val);
if (val == null || int.parse (val[0]) < 1)
return Meta.ShadowParams () {radius = 1, top_fade = 0, x_offset = 0, y_offset = 0, opacity = 0};
return Meta.ShadowParams () {radius = int.parse (val[0]), top_fade = int.parse (val[1]),
return Meta.ShadowParams () {radius = int.parse (val[0]), top_fade = int.parse (val[1]),
x_offset = int.parse (val[2]), y_offset = int.parse (val[3]), opacity = (uint8)int.parse (val[4])};
}
}
public class AnimationSettings : Granite.Services.Settings
{
public bool enable_animations { get; set; }
@ -135,19 +135,19 @@ namespace Gala
public int minimize_duration { get; set; }
public int workspace_switch_duration { get; set; }
public int menu_duration { get; set; }
static AnimationSettings? instance = null;
private AnimationSettings ()
{
base (Config.SCHEMA + ".animations");
}
public static AnimationSettings get_default ()
{
if (instance == null)
instance = new AnimationSettings ();
return instance;
}
}

View File

@ -1,19 +1,19 @@
//
//
// Copyright (C) 2012 Tom Beckmann, Rico Tzschichholz
//
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
namespace Gala
{
@ -24,34 +24,34 @@ namespace Gala
get { return _offset_y; }
set { _offset_y = value; update (); }
}
int _offset_x;
public int offset_x {
get { return _offset_x; }
set { _offset_x = value; update (); }
}
uint8 _opacity;
public uint8 opacity {
get { return _opacity; }
set { _opacity = value; update (); }
}
public TextShadowEffect (int offset_x, int offset_y, uint8 opacity)
{
_offset_x = offset_x;
_offset_y = offset_y;
_opacity = opacity;
}
public override bool pre_paint ()
{
var layout = ((Clutter.Text)get_actor ()).get_layout ();
Cogl.pango_render_layout (layout, offset_x, offset_y, Cogl.Color.from_4ub (0, 0, 0, opacity), 0);
return true;
}
public void update ()
{
if (get_actor () != null)

View File

@ -1,19 +1,19 @@
//
//
// Copyright (C) 2012 Tom Beckmann
//
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
using Clutter;
using Meta;
@ -23,28 +23,28 @@ namespace Gala
public class AppIcon : GtkClutter.Texture
{
const string DRAG_ACTION = "drag";
Window window;
Bamf.Application app;
public AppIcon (Window _window, Bamf.Application _app)
{
window = _window;
app = _app;
try {
set_from_pixbuf (Utils.get_icon_for_window (window, WorkspaceThumb.APP_ICON_SIZE));
} catch (Error e) { warning (e.message); }
var action = new DragDropAction (DragDropActionType.SOURCE, WorkspaceThumb.DRAG_ID);
action.drag_begin.connect (drag_begin);
action.drag_end.connect (drag_end);
action.drag_canceled.connect (drag_canceled);
add_action_with_name (DRAG_ACTION, action);
reactive = true;
}
void drag_canceled ()
{
var action = get_action (DRAG_ACTION) as DragDropAction;
@ -66,11 +66,11 @@ namespace Gala
WorkspaceThumb old = get_parent ().get_parent () as WorkspaceThumb;
get_parent ().remove_child (this);
opacity = 255;
var dest_thumb = destination as WorkspaceThumb;
var icons = dest_thumb.icons;
var wallpaper = dest_thumb.wallpaper;
icons.add_child (this);
// get all the windows that belong to this app, if possible
@ -85,21 +85,21 @@ namespace Gala
}
} else
window.change_workspace (dest_thumb.workspace);
if (old != null)
old.icons.animate (AnimationMode.LINEAR, 100, x:Math.floorf (old.wallpaper.x + old.wallpaper.width / 2 - old.icons.width / 2));
icons.animate (AnimationMode.LINEAR, 100, x:Math.floorf (wallpaper.x + wallpaper.width / 2 - icons.width / 2));
}
Clutter.Actor drag_begin ()
{
opacity = 0;
var handle = new Clone (this);
get_stage ().add_child (handle);
return handle;
}
}
}

View File

@ -5,7 +5,7 @@ namespace Gala
public class MultitaskingView : Actor
{
public Meta.Screen screen { get; construct set; }
public Plugin plugin { get; construct set; }
public WindowManager wm { get; construct set; }
Actor icon_groups;
Actor workspaces;
@ -14,9 +14,9 @@ namespace Gala
const int HIDING_DURATION = 300;
public MultitaskingView (Plugin plugin)
public MultitaskingView (WindowManager wm)
{
Object (plugin: plugin, screen: plugin.get_screen ());
Object (wm: wm, screen: wm.get_screen ());
visible = false;
reactive = true;
@ -152,11 +152,11 @@ namespace Gala
var monitor = screen.get_monitor_geometry (primary_monitor);
if (opening) {
plugin.begin_modal ();
wm.begin_modal ();
plugin.background_group.hide ();
plugin.window_group.hide ();
plugin.top_window_group.hide ();
wm.background_group.hide ();
wm.window_group.hide ();
wm.top_window_group.hide ();
show ();
grab_key_focus ();
@ -190,11 +190,11 @@ namespace Gala
Timeout.add (290, () => {
hide ();
plugin.background_group.show ();
plugin.window_group.show ();
plugin.top_window_group.show ();
wm.background_group.show ();
wm.window_group.show ();
wm.top_window_group.show ();
plugin.end_modal ();
wm.end_modal ();
return false;
});

View File

@ -20,7 +20,7 @@ using Clutter;
namespace Gala
{
public enum WindowOverviewType
{
GRID = 0,
@ -28,31 +28,31 @@ namespace Gala
}
public delegate void WindowPlacer (Actor window, Meta.Rectangle rect);
public class WindowOverview : Actor
{
Plugin plugin;
WindowManager wm;
Screen screen;
bool ready;
//the workspaces which we expose right now
List<Workspace> workspaces;
static const int PADDING = 50;
public WindowOverview (Plugin _plugin)
public WindowOverview (WindowManager _wm)
{
plugin = _plugin;
screen = plugin.get_screen ();
wm = _wm;
screen = wm.get_screen ();
screen.workspace_switched.connect (() => close (false));
visible = false;
ready = true;
reactive = true;
}
public override bool key_press_event (Clutter.KeyEvent event)
{
//FIXME need to figure out the actual keycombo, for now leave it by
@ -61,31 +61,31 @@ namespace Gala
event.keyval == Clutter.Key.a ||
event.keyval == Clutter.Key.Escape) {
close (true);
return true;
}
return false;
}
public override void key_focus_out ()
{
close (false);
}
public override bool button_release_event (Clutter.ButtonEvent event)
{
if (event.button == 1)
close (true);
return true;
}
/**
* Code ported from KWin present windows effect
* https://projects.kde.org/projects/kde/kde-workspace/repository/revisions/master/entry/kwin/effects/presentwindows/presentwindows.cpp
**/
//constants, mainly for natural expo
const int GAPS = 10;
const int MAX_TRANSLATIONS = 100000;
@ -93,16 +93,16 @@ namespace Gala
const int BORDER = 10;
const int TOP_GAP = 20;
const int BOTTOM_GAP = 100;
//some math utilities
static int squared_distance (Gdk.Point a, Gdk.Point b)
{
var k1 = b.x - a.x;
var k2 = b.y - a.y;
return k1*k1 + k2*k2;
}
static bool rect_is_overlapping_any (Meta.Rectangle rect, Meta.Rectangle[] rects, Meta.Rectangle border)
{
if (!border.contains_rect (rect))
@ -110,25 +110,25 @@ namespace Gala
foreach (var comp in rects) {
if (comp == rect)
continue;
if (rect.overlap (comp))
return true;
}
return false;
}
static Meta.Rectangle rect_adjusted (Meta.Rectangle rect, int dx1, int dy1, int dx2, int dy2)
{
return {rect.x + dx1, rect.y + dy1, rect.width + (-dx1 + dx2), rect.height + (-dy1 + dy2)};
}
static Gdk.Point rect_center (Meta.Rectangle rect)
{
return {rect.x + rect.width / 2, rect.y + rect.height / 2};
}
void calculate_places (List<Actor> windows)
{
var clones = windows.copy ();
@ -136,11 +136,11 @@ namespace Gala
return (int)(a as WindowThumb).window.get_stable_sequence () -
(int)(b as WindowThumb).window.get_stable_sequence ();
});
//sort windows by monitor
List<Actor>[] monitors = {};
monitors.resize (screen.get_n_monitors ());
foreach (var clone in clones) {
// we had some crashes here so there's a reasonable suspicion
// that get_monitor() could be larger than get_n_monitors()
@ -152,37 +152,37 @@ namespace Gala
}
monitors[index].append (clone);
}
for (var i = 0; i < screen.get_n_monitors (); i++) {
if (monitors[i].length () == 0)
continue;
// get the area used by the expo algorithms together
var geom = screen.get_monitor_geometry (i);
Meta.Rectangle area = {(int)Math.floorf (geom.x + BORDER),
(int)Math.floorf (geom.y + TOP_GAP),
(int)Math.floorf (geom.width - BORDER * 2),
(int)Math.floorf (geom.height - BOTTOM_GAP)};
if (BehaviorSettings.get_default ().schema.get_enum ("window-overview-type") == WindowOverviewType.GRID)
grid_placement (area, monitors[i], place_window);
else
natural_placement (area, monitors[i]);
}
}
public static void grid_placement (Meta.Rectangle area, List<Actor> clones, WindowPlacer place)
{
int columns = (int)Math.ceil (Math.sqrt (clones.length ()));
int rows = (int)Math.ceil (clones.length () / (double)columns);
// Assign slots
int slot_width = area.width / columns;
int slot_height = area.height / rows;
WindowThumb[] taken_slots = {};
taken_slots.resize (rows * columns);
// precalculate all slot centers
Gdk.Point[] slot_centers = {};
slot_centers.resize (rows * columns);
@ -192,31 +192,31 @@ namespace Gala
area.y + slot_height * y + slot_height / 2};
}
}
// Assign each window to the closest available slot
var tmplist = clones.copy ();
var window_count = tmplist.length ();
while (tmplist.length () > 0) {
var window = tmplist.nth_data (0) as WindowThumb;
var rect = window.window.get_outer_rect ();
var slot_candidate = -1;
var slot_candidate_distance = int.MAX;
var pos = rect_center (rect);
// all slots
for (int i = 0; i < columns * rows; i++) {
if (i > window_count - 1)
break;
var dist = squared_distance (pos, slot_centers[i]);
if (dist < slot_candidate_distance) {
// window is interested in this slot
WindowThumb occupier = taken_slots[i];
if (occupier == window)
continue;
if (occupier == null || dist < squared_distance (rect_center (occupier.window.get_outer_rect ()), slot_centers[i])) {
// either nobody lives here, or we're better - takeover the slot if it's our best
slot_candidate = i;
@ -224,35 +224,35 @@ namespace Gala
}
}
}
if (slot_candidate == -1)
continue;
if (taken_slots[slot_candidate] != null)
tmplist.prepend (taken_slots[slot_candidate]);
tmplist.remove_all (window);
taken_slots[slot_candidate] = window;
}
//see how many windows we have on the last row
int left_over = (int)clones.length () - columns * (rows - 1);
for (int slot = 0; slot < columns * rows; slot++) {
var window = taken_slots[slot];
// some slots might be empty
if (window == null)
continue;
var rect = window.window.get_outer_rect ();
// Work out where the slot is
Meta.Rectangle target = {area.x + (slot % columns) * slot_width,
area.y + (slot / columns) * slot_height,
slot_width,
slot_height};
target = rect_adjusted (target, 10, 10, -10, -10);
float scale;
if (target.width / (double)rect.width < target.height / (double)rect.height) {
// Center vertically
@ -265,7 +265,7 @@ namespace Gala
target.x += (target.width - (int)(rect.width * scale)) / 2;
target.width = (int)Math.floorf (rect.width * scale);
}
// Don't scale the windows too much
if (scale > 1.0) {
scale = 1.0f;
@ -274,37 +274,37 @@ namespace Gala
(int)Math.floorf (scale * rect.width),
(int)Math.floorf (scale * rect.height)};
}
//put the last row in the center, if necessary
if (left_over != columns && slot >= columns * (rows - 1))
target.x += (columns - left_over) * slot_width / 2;
place (window, target);
}
}
void natural_placement (Meta.Rectangle area, List<Actor> clones)
{
Meta.Rectangle bounds = {area.x, area.y, area.width, area.height};
var direction = 0;
int[] directions = new int[clones.length ()];
Meta.Rectangle[] rects = new Meta.Rectangle[clones.length ()];
for (int i = 0; i < clones.length (); i++) {
// save rectangles into 4-dimensional arrays representing two corners of the rectangular: [left_x, top_y, right_x, bottom_y]
var rect = (clones.nth_data (i) as WindowThumb).window.get_outer_rect ();
rect = rect_adjusted(rect, -GAPS, -GAPS, GAPS, GAPS);
rects[i] = rect;
bounds = bounds.union (rect);
// This is used when the window is on the edge of the screen to try to use as much screen real estate as possible.
directions[i] = direction;
direction++;
if (direction == 4)
direction = 0;
}
var loop_counter = 0;
var overlap = false;
do {
@ -313,25 +313,25 @@ namespace Gala
for (var j = 0; j < rects.length; j++) {
if (i == j)
continue;
var rect = rects[i];
var comp = rects[j];
if (!rect.overlap (comp))
continue;
loop_counter ++;
overlap = true;
// Determine pushing direction
Gdk.Point i_center = rect_center (rect);
Gdk.Point j_center = rect_center (comp);
Gdk.Point diff = {j_center.x - i_center.x, j_center.y - i_center.y};
// Prevent dividing by zero and non-movement
if (diff.x == 0 && diff.y == 0)
diff.x = 1;
// Approximate a vector of between 10px and 20px in magnitude in the same direction
var length = Math.sqrtf (diff.x * diff.x + diff.y * diff.y);
diff.x = (int)Math.floorf (diff.x * ACCURACY / length);
@ -341,7 +341,7 @@ namespace Gala
rect.y += -diff.y;
comp.x += diff.x;
comp.y += diff.y;
// Try to keep the bounding rect the same aspect as the screen so that more
// screen real estate is utilised. We do this by splitting the screen into nine
// equal sections, if the window center is in any of the corner sections pull the
@ -354,7 +354,7 @@ namespace Gala
// (We are using an old bounding rect for this, hopefully it doesn't matter)
var x_section = (int)Math.roundf ((rect.x - bounds.x) / (bounds.width / 3.0f));
var y_section = (int)Math.roundf ((comp.y - bounds.y) / (bounds.height / 3.0f));
i_center = rect_center (rect);
diff.x = 0;
diff.y = 0;
@ -387,27 +387,27 @@ namespace Gala
rect.x += diff.x;
rect.y += diff.y;
}
// Update bounding rect
bounds = bounds.union(rect);
bounds = bounds.union(comp);
//we took copies from the rects from our list so we need to reassign them
rects[i] = rect;
rects[j] = comp;
}
}
} while (overlap && loop_counter < MAX_TRANSLATIONS);
// Work out scaling by getting the most top-left and most bottom-right window coords.
float scale = Math.fminf (Math.fminf (area.width / (float)bounds.width, area.height / (float)bounds.height), 1.0f);
// Make bounding rect fill the screen size for later steps
bounds.x = (int)Math.floorf (bounds.x - (area.width - bounds.width * scale) / 2);
bounds.y = (int)Math.floorf (bounds.y - (area.height - bounds.height * scale) / 2);
bounds.width = (int)Math.floorf (area.width / scale);
bounds.height = (int)Math.floorf (area.height / scale);
// Move all windows back onto the screen and set their scale
var index = 0;
foreach (var rect in rects) {
@ -415,26 +415,26 @@ namespace Gala
(int)Math.floorf ((rect.y - bounds.y) * scale + area.y),
(int)Math.floorf (rect.width * scale),
(int)Math.floorf (rect.height * scale)};
rects[index] = rect;
index++;
}
// fill gaps by enlarging windows
bool moved = false;
Meta.Rectangle border = area;
do {
moved = false;
index = 0;
foreach (var rect in rects) {
int width_diff = ACCURACY;
int height_diff = (int)Math.floorf ((((rect.width + width_diff) - rect.height) /
(float)rect.width) * rect.height);
int x_diff = width_diff / 2;
int y_diff = height_diff / 2;
//top right
Meta.Rectangle old = rect;
rect = {rect.x + x_diff, rect.y - y_diff - height_diff, rect.width + width_diff, rect.height + width_diff};
@ -442,7 +442,7 @@ namespace Gala
rect = old;
else
moved = true;
//bottom right
old = rect;
rect = {rect.x + x_diff, rect.y + y_diff, rect.width + width_diff, rect.height + width_diff};
@ -450,7 +450,7 @@ namespace Gala
rect = old;
else
moved = true;
//bottom left
old = rect;
rect = {rect.x - x_diff, rect.y + y_diff, rect.width + width_diff, rect.height + width_diff};
@ -458,7 +458,7 @@ namespace Gala
rect = old;
else
moved = true;
//top left
old = rect;
rect = {rect.x - x_diff, rect.y - y_diff - height_diff, rect.width + width_diff, rect.height + width_diff};
@ -466,20 +466,20 @@ namespace Gala
rect = old;
else
moved = true;
rects[index] = rect;
index++;
}
} while (moved);
index = 0;
foreach (var rect in rects) {
var window = clones.nth_data (index) as WindowThumb;
var window_rect = window.window.get_outer_rect ();
rect = rect_adjusted(rect, GAPS, GAPS, -GAPS, -GAPS);
scale = rect.width / (float)window_rect.width;
if (scale > 2.0 || (scale > 1.0 && (window_rect.width > 300 || window_rect.height > 300))) {
scale = (window_rect.width > 300 || window_rect.height > 300) ? 1.0f : 2.0f;
rect = {rect_center (rect).x - (int)Math.floorf (window_rect.width * scale) / 2,
@ -487,24 +487,24 @@ namespace Gala
(int)Math.floorf (window_rect.width * scale),
(int)Math.floorf (window_rect.height * scale)};
}
place_window (window, rect);
index++;
}
}
// animate a window to the given position
void place_window (Actor actor, Meta.Rectangle rect)
{
var clone = actor as WindowThumb;
var fscale = rect.width / clone.width;
//animate the windows and icons to the calculated positions
clone.icon.x = rect.x + Math.floorf (clone.width * fscale / 2.0f - clone.icon.width / 2.0f);
clone.icon.y = rect.y + Math.floorf (clone.height * fscale - 50.0f);
clone.icon.get_parent ().set_child_above_sibling (clone.icon, null);
float offset_x, offset_y, offset_width;
Utils.get_window_frame_offset (clone.window, out offset_x, out offset_y, out offset_width, null);
float button_offset = clone.close_button.width * 0.25f;
@ -520,34 +520,34 @@ namespace Gala
break;
}
clone.close_button.y = rect.y - offset_y * fscale - button_offset;
clone.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 250, scale_x:fscale, scale_y:fscale, x:rect.x+0.0f, y:rect.y+0.0f)
.completed.connect (() => ready = true );
clone.icon.opacity = 0;
clone.icon.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 350, scale_x:1.0f, scale_y:1.0f, opacity:255);
}
public void open (bool animate = true, bool all_windows = false)
{
if (!ready)
return;
if (visible) {
close (true);
return;
}
var used_windows = new SList<Window> ();
workspaces = new List<Workspace> ();
if (all_windows) {
foreach (var workspace in screen.get_workspaces ())
workspaces.append (workspace);
} else {
workspaces.append (screen.get_active_workspace ());
}
foreach (var workspace in workspaces) {
foreach (var window in workspace.list_windows ()) {
if (window.window_type != WindowType.NORMAL &&
@ -559,7 +559,7 @@ namespace Gala
}
if (window.window_type == WindowType.DOCK)
continue;
// skip windows that are on all workspace except we're currently
// processing the workspace it actually belongs to
if (window.is_on_all_workspaces () && window.get_workspace () != workspace)
@ -568,50 +568,45 @@ namespace Gala
used_windows.append (window);
}
}
var n_windows = used_windows.length ();
if (n_windows == 0)
return;
ready = false;
foreach (var workspace in workspaces) {
workspace.window_added.connect (add_window);
workspace.window_removed.connect (remove_window);
}
screen.window_left_monitor.connect (window_left_monitor);
#if !HAS_MUTTER38
Compositor.get_background_actor_for_screen (screen).
animate (AnimationMode.EASE_OUT_QUAD, 350, dim_factor : 0.6);
#endif
// sort windows by stacking order
var windows = screen.get_display ().sort_windows_by_stacking (used_windows);
grab_key_focus ();
plugin.begin_modal ();
wm.begin_modal ();
visible = true;
foreach (var window in windows) {
var actor = window.get_compositor_private () as WindowActor;
if (actor == null)
return;
actor.hide ();
var clone = new WindowThumb (window);
clone.x = actor.x;
clone.y = actor.y;
clone.selected.connect (thumb_selected);
clone.closed.connect (thumb_closed);
add_child (clone);
}
calculate_places (get_children ());
}
@ -630,13 +625,13 @@ namespace Gala
}
}
}
void add_window (Window window)
{
if (!visible || window.get_workspace () != screen.get_active_workspace ()
|| (window.window_type != WindowType.NORMAL && window.window_type != WindowType.DIALOG))
return;
var actor = window.get_compositor_private () as WindowActor;
if (actor == null) {
//the window possibly hasn't reached the compositor yet
@ -648,21 +643,21 @@ namespace Gala
});
return;
}
actor.hide ();
var clone = new WindowThumb (window);
clone.x = actor.x;
clone.y = actor.y;
clone.selected.connect (thumb_selected);
clone.closed.connect (thumb_closed);
add_child (clone);
calculate_places (get_children ());
}
void remove_window (Window window)
{
WindowThumb thumb = null;
@ -670,23 +665,23 @@ namespace Gala
if ((child as WindowThumb).window == window)
thumb = child as WindowThumb;
}
if (thumb != null) {
thumb_closed (thumb);
}
}
void thumb_closed (WindowThumb thumb)
{
thumb.destroy ();
var children = get_children ();
if (children.length () > 0)
calculate_places (children);
else
close (false);
}
void thumb_selected (Window window)
{
if (window.get_workspace () == screen.get_active_workspace ()) {
@ -701,50 +696,45 @@ namespace Gala
});
}
}
void close (bool animate)
{
if (!visible || !ready)
return;
foreach (var workspace in workspaces) {
workspace.window_added.disconnect (add_window);
workspace.window_removed.disconnect (remove_window);
}
screen.window_left_monitor.disconnect (window_left_monitor);
ready = false;
plugin.end_modal ();
plugin.update_input_area ();
wm.end_modal ();
wm.update_input_area ();
foreach (var child in get_children ()) {
var exposed = child as WindowThumb;
exposed.close (animate);
exposed.selected.disconnect (thumb_selected);
}
#if !HAS_MUTTER38
Compositor.get_background_actor_for_screen (screen).
animate (AnimationMode.EASE_OUT_QUAD, 300, dim_factor : 1.0);
#endif
if (animate) {
Clutter.Threads.Timeout.add (300, () => {
visible = false;
ready = true;
foreach (var window in screen.get_active_workspace ().list_windows ()) {
if (window.showing_on_its_workspace ())
(window.get_compositor_private () as Actor).show ();
}
return false;
});
} else {
ready = true;
visible = false;
foreach (var window in screen.get_active_workspace ().list_windows ())
if (window.showing_on_its_workspace ())
(window.get_compositor_private () as Actor).show ();

View File

@ -1,19 +1,19 @@
//
//
// Copyright (C) 2012 Tom Beckmann, Rico Tzschichholz
//
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
using Clutter;
using Granite.Drawing;
@ -22,12 +22,12 @@ namespace Gala
{
public class WindowSwitcher : Clutter.Actor
{
Gala.Plugin plugin;
Gala.WindowManager wm;
Gee.ArrayList<Clutter.Clone> window_clones = new Gee.ArrayList<Clutter.Clone> ();
Meta.Window? current_window;
Meta.WindowActor? dock_window;
Actor dock;
CairoTexture dock_background;
@ -38,68 +38,68 @@ namespace Gala
BindConstraint h_constraint;
bool closing = false;
//estimated value, if possible
float dock_width = 0.0f;
public WindowSwitcher (Gala.Plugin _plugin)
public WindowSwitcher (Gala.WindowManager _wm)
{
plugin = _plugin;
wm = _wm;
//pull drawing methods from libplank
dock_settings = new Plank.DockPreferences.with_filename (Environment.get_user_config_dir () + "/plank/dock1/settings");
dock_settings.notify["Theme"].connect (load_dock_theme);
dock = new Actor ();
dock.layout_manager = new BoxLayout ();
dock.anchor_gravity = Clutter.Gravity.CENTER;
dock_background = new CairoTexture (100, dock_settings.IconSize);
dock_background.anchor_gravity = Clutter.Gravity.CENTER;
dock_background.auto_resize = true;
dock_background.draw.connect (draw_dock_background);
y_constraint = new BindConstraint (dock, BindCoordinate.Y, 0);
h_constraint = new BindConstraint (dock, BindCoordinate.HEIGHT, 0);
dock_background.add_constraint (new BindConstraint (dock, BindCoordinate.X, 0));
dock_background.add_constraint (y_constraint);
dock_background.add_constraint (new BindConstraint (dock, BindCoordinate.WIDTH, 0));
dock_background.add_constraint (h_constraint);
add_child (dock_background);
add_child (dock);
load_dock_theme ();
visible = false;
}
void load_dock_theme ()
{
if (dock_theme != null)
dock_theme.notify.disconnect (update_dock);
dock_theme = new Plank.Drawing.DockTheme (dock_settings.Theme);
dock_theme.load ("dock");
dock_theme.notify.connect (update_dock);
update_dock ();
}
//set the values which don't get set every time and need to be updated when the theme changes
void update_dock ()
{
(dock.layout_manager as BoxLayout).spacing = (uint)(dock_theme.ItemPadding / 10.0 * dock_settings.IconSize);
dock.height = dock_settings.IconSize;
var top_offset = (int)(dock_theme.TopPadding / 10.0 * dock_settings.IconSize);
var bottom_offset = (int)(dock_theme.BottomPadding / 10.0 * dock_settings.IconSize);
y_constraint.offset = -top_offset / 2 + bottom_offset / 2;
h_constraint.offset = top_offset + bottom_offset;
}
bool draw_dock_background (Cairo.Context cr)
{
if (dock_surface == null || dock_surface.Width != dock_background.width) {
@ -107,23 +107,23 @@ namespace Gala
(int)dock_background.height, Gtk.PositionType.BOTTOM,
new Plank.Drawing.DockSurface.with_surface (1, 1, cr.get_target ()));
}
cr.set_source_surface (dock_surface.Internal, 0, 0);
cr.paint ();
return false;
}
public override bool key_release_event (Clutter.KeyEvent event)
{
if (((event.modifier_state & ModifierType.MOD1_MASK) == 0) ||
if (((event.modifier_state & ModifierType.MOD1_MASK) == 0) ||
event.keyval == Key.Alt_L) {
close (event.time);
}
return true;
}
void close (uint time)
{
if (closing)
@ -131,54 +131,54 @@ namespace Gala
closing = true;
var screen = plugin.get_screen ();
var screen = wm.get_screen ();
var workspace = screen.get_active_workspace ();
if (dock_window != null)
dock_window.opacity = 0;
var dest_width = (dock_width > 0 ? dock_width : 600.0f);
dock_width = 0;
set_child_above_sibling (dock, null);
dock_background.animate (AnimationMode.EASE_OUT_CUBIC, 250, opacity : 0);
if (dock_window != null) {
dock_window.show ();
dock_window.animate (AnimationMode.LINEAR, 250, opacity : 255);
}
foreach (var clone in window_clones) {
//current window stays on top
if ((clone.source as Meta.WindowActor).get_meta_window () == current_window)
continue;
//reset order
clone.get_parent ().set_child_below_sibling (clone, null);
if (!(clone.source as Meta.WindowActor).get_meta_window ().minimized)
clone.animate (AnimationMode.EASE_OUT_CUBIC, 150, depth : 0.0f, opacity : 255);
}
if (current_window != null) {
current_window.activate (time);
current_window = null;
}
plugin.end_modal ();
wm.end_modal ();
dock.animate (AnimationMode.EASE_OUT_CUBIC, 250, width:dest_width, opacity : 0).
completed.connect (() => {
dock.remove_all_children ();
if (dock_window != null)
dock_window = null;
visible = false;
foreach (var clone in window_clones)
remove_clone (clone);
window_clones.clear ();
//need to go through all the windows because of hidden dialogs
unowned List<Meta.WindowActor>? window_actors = Meta.Compositor.get_window_actors (screen);
warn_if_fail (window_actors != null);
@ -195,57 +195,53 @@ namespace Gala
screen.window_left_monitor.disconnect (window_left_monitor);
});
}
//used to figure out delays between switching when holding the tab key
uint last_time = -1;
bool released = false;
public override bool captured_event (Clutter.Event event)
{
var screen = plugin.get_screen ();
var screen = wm.get_screen ();
var display = screen.get_display ();
if (event.get_type () == EventType.KEY_RELEASE) {
released = true;
return false;
}
if (!(event.get_type () == EventType.KEY_PRESS) ||
if (!(event.get_type () == EventType.KEY_PRESS) ||
(!released && display.get_current_time_roundtrip () < (last_time + 300)))
return false;
released = false;
bool backward = (event.get_state () & X.KeyMask.ShiftMask) != 0;
var action = display.get_keybinding_action (event.get_key_code (), event.get_state ());
var prev_win = current_window;
if (action == Meta.KeyBindingAction.SWITCH_GROUP ||
action == Meta.KeyBindingAction.SWITCH_WINDOWS ||
#if HAS_MUTTER38
action == Meta.KeyBindingAction.SWITCH_WINDOWS ||
action == Meta.KeyBindingAction.SWITCH_APPLICATIONS ||
#endif
event.get_key_symbol () == Clutter.Key.Right) {
current_window = display.get_tab_next (Meta.TabList.NORMAL, screen,
current_window = display.get_tab_next (Meta.TabList.NORMAL, screen,
screen.get_active_workspace (), current_window, backward);
last_time = display.get_current_time_roundtrip ();
} else if (action == Meta.KeyBindingAction.SWITCH_GROUP_BACKWARD ||
action == Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD ||
#if HAS_MUTTER38
action == Meta.KeyBindingAction.SWITCH_APPLICATIONS_BACKWARD ||
#endif
event.get_key_symbol () == Clutter.Key.Left) {
current_window = display.get_tab_next (Meta.TabList.NORMAL, screen,
current_window = display.get_tab_next (Meta.TabList.NORMAL, screen,
screen.get_active_workspace (), current_window, true);
last_time = display.get_current_time_roundtrip ();
}
if (prev_win != current_window) {
dim_windows ();
}
return true;
}
@ -255,10 +251,10 @@ namespace Gala
if (dock.get_child_at_index (index) == event.source)
break;
}
var prev_window = current_window;
current_window = (window_clones.get (index).source as Meta.WindowActor).get_meta_window ();
if (prev_window != current_window) {
dim_windows ();
// wait for the dimming to finish
@ -272,7 +268,7 @@ namespace Gala
return true;
}
void dim_windows ()
{
var current_actor = current_window.get_compositor_private () as Actor;
@ -281,13 +277,13 @@ namespace Gala
if (current_actor == clone.source) {
set_child_below_sibling (clone, dock_background);
clone.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 250, depth : 0.0f, opacity : 255);
dock.get_child_at_index (i).animate (AnimationMode.LINEAR, 100, opacity : 255);
} else {
clone.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 250, depth : -200.0f, opacity : 0);
dock.get_child_at_index (i).animate (AnimationMode.LINEAR, 100, opacity : 100);
}
i++;
}
}
@ -295,24 +291,19 @@ namespace Gala
void window_left_monitor (int num, Meta.Window window)
{
// see if that's happened on our workspace
var workspace = plugin.get_screen ().get_active_workspace ();
#if HAS_MUTTER38
var workspace = wm.get_screen ().get_active_workspace ();
if (window.located_on_workspace (workspace)) {
#else
if (window.get_workspace () == workspace ||
(window.is_on_all_workspaces () && window.get_screen () == workspace.get_screen ())) {
#endif
remove_window (window);
}
}
void add_window (Meta.Window window)
{
var screen = plugin.get_screen ();
var screen = wm.get_screen ();
if (window.get_workspace () != screen.get_active_workspace ())
return;
var actor = window.get_compositor_private () as Meta.WindowActor;
if (actor == null) {
//the window possibly hasn't reached the compositor yet
@ -324,19 +315,19 @@ namespace Gala
});
return;
}
if (actor.is_destroyed ())
return;
actor.hide ();
var clone = new Clone (actor);
clone.x = actor.x;
clone.y = actor.y;
add_child (clone);
window_clones.add (clone);
var icon = new GtkClutter.Texture ();
icon.reactive = true;
icon.button_release_event.connect (clicked_icon);
@ -344,11 +335,11 @@ namespace Gala
var pix = Utils.get_icon_for_window (window, dock_settings.IconSize);
icon.set_from_pixbuf (pix);
} catch (Error e) { warning (e.message); }
icon.opacity = 100;
dock.add_child (icon);
(dock.layout_manager as BoxLayout).set_expand (icon, true);
//if the window has been added while being in alt-tab, redim
if (visible) {
float dest_width;
@ -357,26 +348,26 @@ namespace Gala
dim_windows ();
}
}
void remove_clone (Clone clone)
{
var window = clone.source as Meta.WindowActor;
var meta_win = window.get_meta_window ();
if (meta_win != null &&
!window.is_destroyed () &&
!meta_win.minimized &&
(meta_win.get_workspace () == plugin.get_screen ().get_active_workspace ()) ||
(meta_win.get_workspace () == wm.get_screen ().get_active_workspace ()) ||
meta_win.is_on_all_workspaces ())
window.show ();
clone.destroy ();
float dest_width;
dock.layout_manager.get_preferred_width (dock, dock.height, null, out dest_width);
dock.animate (AnimationMode.EASE_OUT_CUBIC, 400, width : dest_width);
}
void remove_window (Meta.Window window)
{
Clone found = null;
@ -386,24 +377,24 @@ namespace Gala
break;
}
}
if (found == null) {
warning ("No clone found for removed window");
return;
}
var icon = dock.get_child_at_index (window_clones.index_of (found));
icon.button_release_event.disconnect (clicked_icon);
icon.destroy ();
window_clones.remove (found);
remove_clone (found);
}
public override void key_focus_out ()
{
close (plugin.get_screen ().get_display ().get_current_time ());
close (wm.get_screen ().get_display ().get_current_time ());
}
public void handle_switch_windows (Meta.Display display, Meta.Screen screen, Meta.Window? window,
X.Event event, Meta.KeyBinding binding)
{
@ -412,9 +403,9 @@ namespace Gala
close (screen.get_display ().get_current_time ());
return;
}
var workspace = screen.get_active_workspace ();
var metawindows = display.get_tab_list (Meta.TabList.NORMAL, screen, workspace);
if (metawindows.length () == 0)
return;
@ -427,48 +418,48 @@ namespace Gala
return;
}
}
workspace.window_added.connect (add_window);
workspace.window_removed.connect (remove_window);
screen.window_left_monitor.connect (window_left_monitor);
//grab the windows to be switched
var layout = dock.layout_manager as BoxLayout;
window_clones.clear ();
foreach (var win in metawindows)
add_window (win);
visible = true;
//hide the others
Meta.Compositor.get_window_actors (screen).foreach ((w) => {
var type = w.get_meta_window ().window_type;
if (type != Meta.WindowType.DOCK && type != Meta.WindowType.DESKTOP && type != Meta.WindowType.NOTIFICATION)
w.hide ();
if (w.get_meta_window ().title in BehaviorSettings.get_default ().dock_names && type == Meta.WindowType.DOCK) {
dock_window = w;
dock_window.hide ();
}
});
closing = false;
plugin.begin_modal ();
wm.begin_modal ();
bool backward = (binding.get_name () == "switch-windows-backward");
current_window = Utils.get_next_window (screen.get_active_workspace (), backward);
if (current_window == null)
return;
if (binding.get_mask () == 0) {
current_window.activate (display.get_current_time ());
return;
}
//plank type switcher thing
var geometry = screen.get_monitor_geometry (screen.get_primary_monitor ());
dock.width = (dock_window != null ? dock_window.width : 300.0f);
//FIXME do this better
//count the launcher items to get an estimate of the window size
@ -479,34 +470,34 @@ namespace Gala
var children = launcher_folder.enumerate_children ("", 0);
while (children.next_file () != null)
count ++;
if (count > 0)
dock.width = count * (float)(dock_settings.IconSize + dock_theme.ItemPadding);
dock_width = dock.width;
} catch (Error e) { warning (e.message); }
}
var bottom_offset = (int)(dock_theme.BottomPadding / 10.0 * dock_settings.IconSize);
dock.opacity = 255;
dock.x = Math.ceilf (geometry.x + geometry.width / 2.0f);
dock.y = Math.ceilf (geometry.y + geometry.height - dock.height / 2.0f) - bottom_offset;
//add spacing on outer most items
var horiz_padding = (float) Math.ceil (dock_theme.HorizPadding / 10.0 * dock_settings.IconSize + layout.spacing / 2.0);
dock.get_first_child ().margin_left = horiz_padding;
dock.get_last_child ().margin_right = horiz_padding;
float dest_width;
layout.get_preferred_width (dock, dock.height, null, out dest_width);
set_child_above_sibling (dock_background, null);
dock_background.opacity = 255;
dock.animate (AnimationMode.EASE_OUT_CUBIC, 250, width : dest_width);
set_child_above_sibling (dock, null);
dim_windows ();
grab_key_focus ();
@ -514,7 +505,7 @@ namespace Gala
Gdk.Display.get_default ().get_device_manager ().get_client_pointer ().get_state (Gdk.get_default_root_window (),
null, out modifiers);
if ((modifiers & Gdk.ModifierType.MOD1_MASK) == 0)
close (plugin.get_screen ().get_display ().get_current_time ());
close (wm.get_screen ().get_display ().get_current_time ());
}
}
}

View File

@ -28,30 +28,30 @@ namespace Gala
public GtkClutter.Texture close_button;
const int WAIT_FOR_CONFIRMATION_DIALOG = 100;
public signal void selected (Window window);
public signal void closed ();
public WindowThumb (Window _window, bool add_children_to_stage = true)
{
window = _window;
reactive = true;
var actor = window.get_compositor_private () as WindowActor;
clone = new Clone (actor);
clone.add_constraint (new BindConstraint (this, BindCoordinate.SIZE, 0));
icon = new GtkClutter.Texture ();
icon.scale_x = 0.0f;
icon.scale_y = 0.0f;
icon.opacity = 0;
icon.scale_gravity = Gravity.CENTER;
try {
icon.set_from_pixbuf (Utils.get_icon_for_window (window, 64));
} catch (Error e) { warning (e.message); }
close_button = new GtkClutter.Texture ();
close_button.reactive = true;
close_button.visible = false;
@ -60,13 +60,13 @@ namespace Gala
close_button.scale_gravity = Gravity.CENTER;
close_button.button_release_event.connect (close_button_clicked);
close_button.leave_event.connect ((e) => leave_event (e));
try {
close_button.set_from_pixbuf (Granite.Widgets.Utils.get_close_pixbuf ());
} catch (Error e) { warning (e.message); }
add_child (clone);
if (add_children_to_stage) {
var stage = Compositor.get_stage_for_screen (window.get_screen ());
stage.add_child (icon);
@ -102,17 +102,17 @@ namespace Gala
icon.animate (AnimationMode.EASE_OUT_CUBIC, 350, scale_x: 1.0f, scale_y: 1.0f, opacity: 255);
}
bool close_button_clicked (ButtonEvent event)
{
if (event.button != 1)
return false;
close_window ();
return true;
}
public void close_window ()
{
get_parent ().set_child_below_sibling (this, null);
@ -135,44 +135,44 @@ namespace Gala
clone.destroy ();
close_button.destroy ();
icon.destroy ();
base.destroy ();
}
public override bool enter_event (CrossingEvent event)
{
//if we're still animating don't show the close button
if (get_animation () != null)
return false;
close_button.visible = true;
close_button.animate (AnimationMode.EASE_OUT_ELASTIC, 400, scale_x : 1.0f, scale_y : 1.0f);
return true;
}
public override bool motion_event (MotionEvent event)
{
if (get_animation () != null)
return false;
close_button.visible = true;
close_button.animate (AnimationMode.EASE_OUT_ELASTIC, 400, scale_x : 1.0f, scale_y : 1.0f);
return true;
}
public override bool leave_event (CrossingEvent event)
{
if (event.related == close_button)
return false;
close_button.animate (AnimationMode.EASE_IN_QUAD, 200, scale_x : 0.0f, scale_y : 0.0f)
.completed.connect (() => close_button.visible = false );
return true;
}
public override bool button_release_event (ButtonEvent event)
{
switch (event.button) {
@ -184,32 +184,32 @@ namespace Gala
close_window ();
break;
}
return true;
}
public void close (bool do_animate = true, bool use_scale = true)
{
unowned Meta.Rectangle rect = window.get_outer_rect ();
float x, y, w, h;
Utils.get_window_frame_offset (window, out x, out y, out w, out h);
float dest_x = rect.x + x;
float dest_y = rect.y + y;
//stop all running animations
detach_animation ();
icon.detach_animation ();
close_button.detach_animation ();
bool dont_show = window.minimized || window.get_workspace () != window.get_screen ().get_active_workspace ();
do_animate = do_animate && !dont_show;
if (do_animate) {
icon.animate (AnimationMode.EASE_IN_CUBIC, 100, scale_x:0.0f, scale_y:0.0f);
close_button.animate (AnimationMode.EASE_IN_QUAD, 200, scale_x : 0.0f, scale_y : 0.0f);
Animation a;
if (use_scale) {
a = animate (AnimationMode.EASE_IN_OUT_CUBIC, 300, scale_x: 1.0f, scale_y: 1.0f,

View File

@ -1,19 +1,19 @@
//
//
// Copyright (C) 2012 Tom Beckmann, Rico Tzschichholz
//
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
using Meta;
using Clutter;
@ -26,87 +26,75 @@ namespace Gala
internal static const int APP_ICON_SIZE = 32;
static const float THUMBNAIL_HEIGHT = 80.0f;
static const uint CLOSE_BUTTON_DELAY = 500;
static const int PLUS_SIZE = 8;
static const int PLUS_WIDTH = 24;
static const int PLUS_OFFSET = 8;
public static const string DRAG_ID = "app-icon";
const string DROP_ACTION = "drop";
public signal void clicked ();
public signal void closed ();
public signal void window_on_last ();
public unowned Workspace? workspace { get; set; }
unowned Screen screen;
static Actor? plus = null;
static Plank.Drawing.DockSurface? buffer = null;
Gtk.StyleContext selector_style;
Gtk.EventBox selector_style_widget;
#if HAS_MUTTER38
internal Actor wallpaper;
Actor wallpaper_manager;
#else
internal Clone wallpaper;
#endif
Clutter.Actor windows;
internal Clutter.Actor icons;
Actor indicator;
GtkClutter.Texture close_button;
uint hover_timer = 0;
#if HAS_MUTTER38
public WorkspaceThumb (Workspace _workspace, Meta.BackgroundGroup _wallpaper)
#else
public WorkspaceThumb (Workspace _workspace)
#endif
{
workspace = _workspace;
screen = workspace.get_screen ();
selector_style_widget = new Gtk.EventBox ();
selector_style_widget.show ();
selector_style = selector_style_widget.get_style_context ();
selector_style.add_class ("gala-workspace-selected");
selector_style.add_provider (Utils.get_default_style (), Gtk.STYLE_PROVIDER_PRIORITY_FALLBACK);
screen.workspace_switched.connect (handle_workspace_switched);
screen.workspace_added.connect (workspace_added);
screen.monitors_changed.connect (resize);
workspace.window_added.connect (handle_window_added);
workspace.window_removed.connect (handle_window_removed);
screen.window_left_monitor.connect (window_left_monitor);
reactive = true;
indicator = new Actor ();
indicator.height = THUMBNAIL_HEIGHT + 2 * INDICATOR_BORDER;
indicator.opacity = 0;
indicator.content = new Canvas ();
(indicator.content as Canvas).draw.connect (draw_indicator);
handle_workspace_switched (-1, screen.get_active_workspace_index (), MotionDirection.LEFT);
#if HAS_MUTTER38
wallpaper_manager = new BackgroundManager (screen);
//FIXME apparently there are issues with scaling and animating the opacity. The wallpaper will
// start flickering when the opacity changes. Wrapping it in a container solves this.
wallpaper = new Clutter.Actor ();
wallpaper.add_child (wallpaper_manager);
#else
wallpaper = new Clone (Compositor.get_background_actor_for_screen (screen));
#endif
wallpaper.x = INDICATOR_BORDER;
wallpaper.y = INDICATOR_BORDER;
wallpaper.height = THUMBNAIL_HEIGHT;
close_button = new GtkClutter.Texture ();
try {
close_button.set_from_pixbuf (Granite.Widgets.Utils.get_close_pixbuf ());
@ -116,18 +104,18 @@ namespace Gala
close_button.scale_gravity = Clutter.Gravity.CENTER;
close_button.scale_x = 0;
close_button.scale_y = 0;
icons = new Actor ();
icons.layout_manager = new BoxLayout ();
(icons.layout_manager as Clutter.BoxLayout).spacing = 6;
icons.height = APP_ICON_SIZE;
windows = new Actor ();
windows.x = INDICATOR_BORDER;
windows.y = INDICATOR_BORDER;
windows.height = THUMBNAIL_HEIGHT;
windows.clip_to_allocation = true;
add_child (indicator);
add_child (wallpaper);
add_child (windows);
@ -137,18 +125,18 @@ namespace Gala
var click = new ClickAction ();
add_action (click);
click.clicked.connect (pressed);
//kill the workspace
var close_click = new ClickAction ();
close_button.add_action (close_click);
close_click.clicked.connect (close_workspace);
if (plus == null) {
plus = new Actor ();
var canvas = new Canvas ();
plus.content = canvas;
canvas.draw.connect ((cr) => {
// putting the buffer inside here is not a problem performance-wise,
// putting the buffer inside here is not a problem performance-wise,
// as the method will only be called once anyway
var buffer = new Granite.Drawing.BufferSurface (canvas.width, canvas.height);
@ -180,18 +168,18 @@ namespace Gala
plus.height = PLUS_WIDTH + 2 * PLUS_OFFSET;
canvas.set_size ((int)plus.width, (int)plus.height);
}
var drop_action = new DragDropAction (DragDropActionType.DESTINATION, DRAG_ID);
add_action_with_name (DROP_ACTION, drop_action);
drop_action.crossed.connect (crossed);
check_last_workspace ();
visible = false;
var canvas = new Canvas ();
canvas.draw.connect (draw_background);
content = canvas;
resize (screen);
@ -202,7 +190,7 @@ namespace Gala
{
int swidth, sheight;
screen.get_size (out swidth, out sheight);
// make sure we redraw the buffer
buffer = null;
@ -210,10 +198,8 @@ namespace Gala
indicator.width = width + 2 * INDICATOR_BORDER;
(indicator.content as Canvas).set_size ((int)indicator.width, (int)indicator.height);
#if HAS_MUTTER38
wallpaper_manager.scale_x = width / swidth;
wallpaper_manager.scale_y = THUMBNAIL_HEIGHT / sheight;
#endif
wallpaper.width = width;
windows.width = width;
@ -250,7 +236,7 @@ namespace Gala
Cogl.set_source_color4f (1, 1, 1, 0.3f);
Cogl.Path.stroke ();
}
void crossed (bool over)
{
// when draggin, the leave event isn't emitted
@ -263,7 +249,7 @@ namespace Gala
indicator.animate (AnimationMode.LINEAR, 100, opacity: over ? 200 : 0);
}
~WorkspaceThumb ()
{
screen.workspace_switched.disconnect (handle_workspace_switched);
@ -271,7 +257,7 @@ namespace Gala
screen.monitors_changed.disconnect (resize);
screen.window_left_monitor.disconnect (window_left_monitor);
}
void close_workspace (Clutter.Actor actor)
{
if (workspace == null)
@ -281,73 +267,68 @@ namespace Gala
if (window.window_type != WindowType.DOCK)
window.delete (screen.get_display ().get_current_time ());
}
Clutter.Threads.Timeout.add (250, () => {
//wait for confirmation dialogs to popup
if (Utils.get_n_windows (workspace) == 0) {
workspace.window_added.disconnect (handle_window_added);
workspace.window_removed.disconnect (handle_window_removed);
animate (Clutter.AnimationMode.LINEAR, 250, width : 0.0f, opacity : 0);
closed ();
} else
workspace.activate (workspace.get_screen ().get_display ().get_current_time ());
return false;
});
}
bool draw_indicator (Cairo.Context cr)
{
cr.set_operator (Cairo.Operator.CLEAR);
cr.paint ();
cr.set_operator (Cairo.Operator.OVER);
selector_style.render_background (cr, 0, 0, indicator.width, indicator.height);
selector_style.render_frame (cr, 0, 0, indicator.width, indicator.height);
return false;
}
bool draw_background (Cairo.Context cr)
{
if (buffer == null) {
buffer = new Plank.Drawing.DockSurface ((int)width, (int)height);
// some weird calculations are necessary here, we have to
// some weird calculations are necessary here, we have to
// subtract the delta of the wallpaper and container size to make it fit
buffer.Context.rectangle (wallpaper.x, wallpaper.y,
buffer.Context.rectangle (wallpaper.x, wallpaper.y,
wallpaper.width - (width - wallpaper.width),
wallpaper.height - (height - wallpaper.height) - INDICATOR_BORDER);
buffer.Context.set_source_rgba (0, 0, 0, 1);
buffer.Context.fill ();
buffer.exponential_blur (5);
}
cr.set_operator (Cairo.Operator.CLEAR);
cr.paint ();
cr.set_operator (Cairo.Operator.OVER);
cr.set_source_surface (buffer.Internal, 0, 0);
cr.paint ();
return false;
}
void workspace_added (int index)
{
check_last_workspace ();
}
void window_left_monitor (int num, Meta.Window window)
{
#if HAS_MUTTER38
if (window.located_on_workspace (workspace))
#else
if (window.get_workspace () == workspace ||
(window.is_on_all_workspaces () && window.get_screen () == workspace.get_screen ()))
#endif
handle_window_removed (window);
}
@ -356,10 +337,10 @@ namespace Gala
windows.remove_all_children ();
if (workspace == null)
return;
int swidth, sheight;
screen.get_size (out swidth, out sheight);
// add window thumbnails
var aspect = windows.width / swidth;
@ -367,7 +348,7 @@ namespace Gala
var list = new SList<Window> ();
foreach (var window in unordered) {
if (!window.minimized &&
(window.window_type == WindowType.NORMAL ||
(window.window_type == WindowType.NORMAL ||
window.window_type == WindowType.DIALOG ||
window.window_type == WindowType.MODAL_DIALOG))
list.prepend (window);
@ -384,55 +365,55 @@ namespace Gala
clone.height = aspect * clone.height;
clone.x = aspect * actor.x;
clone.y = aspect * actor.y;
windows.add_child (clone);
}
}
void update_icons ()
{
icons.remove_all_children ();
if (workspace == null)
return;
//show each icon only once, so log the ones added
var shown_applications = new List<Bamf.Application> ();
workspace.list_windows ().foreach ((w) => {
if (w.window_type != Meta.WindowType.NORMAL || w.minimized)
return;
var app = Bamf.Matcher.get_default ().get_application_for_xid ((uint32)w.get_xwindow ());
if (shown_applications.index (app) != -1)
return;
if (app != null)
shown_applications.append (app);
var icon = new AppIcon (w, app);
icons.add_child (icon);
});
icons.x = Math.floorf (wallpaper.x + wallpaper.width / 2 - icons.width / 2);
icons.y = Math.floorf (wallpaper.y + wallpaper.height - 5);
}
void check_last_workspace ()
{
if (!Prefs.get_dynamic_workspaces ())
return;
//last workspace, show plus button and so on
//give the last one a different style
var index = screen.get_workspaces ().index (workspace);
if (index < 0) {
closed ();
return;
}
if (index == screen.n_workspaces - 1) {
wallpaper.opacity = 127;
if (plus.get_parent () != null)
@ -444,21 +425,21 @@ namespace Gala
remove_child (plus);
}
}
void handle_workspace_switched (int index_old, int index_new, Meta.MotionDirection direction)
{
if (index_old == index_new)
return;
if (workspace == null)
return;
if (workspace.index () == index_old)
indicator.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 200, opacity : 0);
else if (workspace.index () == index_new)
indicator.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 200, opacity : 255);
}
void handle_window_added (Meta.Window window)
{
// wait till the window is ready
@ -470,24 +451,24 @@ namespace Gala
});
return;
}
if (visible) {
update_windows ();
update_icons ();
}
if (!Prefs.get_dynamic_workspaces ())
return;
if (workspace != null && workspace.index () == screen.n_workspaces - 1 && Utils.get_n_windows (workspace) > 0)
window_on_last ();
}
void handle_window_removed (Meta.Window window)
{
if (visible)
update_windows ();
if (!Prefs.get_dynamic_workspaces ()
|| (window.window_type != WindowType.NORMAL
&& window.window_type != WindowType.DIALOG
@ -496,106 +477,106 @@ namespace Gala
|| Utils.get_n_windows (workspace) > 0
|| workspace.index () == workspace.get_screen ().get_n_workspaces () - 1)
return;
// we need to wait untill the animation ended, otherwise we get trouble with focus handling
Clutter.Threads.Timeout.add (AnimationSettings.get_default ().workspace_switch_duration + 10, () => {
// check again, maybe something opened
if (workspace == null || Utils.get_n_windows (workspace) > 0)
return false;
workspace.window_added.disconnect (handle_window_added);
workspace.window_removed.disconnect (handle_window_removed);
closed ();
return false;
});
}
public override void hide ()
{
base.hide ();
icons.remove_all_children ();
windows.remove_all_children ();
}
public override void show ()
{
check_last_workspace ();
update_icons ();
update_windows ();
base.show ();
}
public void pressed (Actor actor)
{
if (workspace == null)
return;
workspace.activate (screen.get_display ().get_current_time ());
// wait for the animation to be finished before closing, for aesthetic reasons
Clutter.Threads.Timeout.add (AnimationSettings.get_default ().workspace_switch_duration, () => {
clicked ();
return false;
});
}
public override bool enter_event (CrossingEvent event)
{
if (workspace == null)
return true;
if (!Prefs.get_dynamic_workspaces ())
return false;
if (workspace.index () == screen.n_workspaces - 1) {
wallpaper.animate (AnimationMode.EASE_OUT_QUAD, 300, opacity : 210);
return true;
}
//dont allow closing the tab if it's the last one used
if (workspace.index () == 0 && screen.n_workspaces == 2)
return false;
if (hover_timer > 0)
GLib.Source.remove (hover_timer);
hover_timer = Clutter.Threads.Timeout.add (CLOSE_BUTTON_DELAY, () => {
close_button.visible = true;
close_button.animate (AnimationMode.EASE_OUT_ELASTIC, 400, scale_x : 1.0f, scale_y : 1.0f);
return false;
});
return true;
}
internal void hide_close_button ()
{
close_button.animate (AnimationMode.EASE_IN_QUAD, 400, scale_x : 0.0f, scale_y : 0.0f)
.completed.connect (() => close_button.visible = false );
}
public override bool leave_event (CrossingEvent event)
{
if (contains (event.related))
return false;
if (hover_timer > 0) {
GLib.Source.remove (hover_timer);
hover_timer = 0;
}
if (workspace == null)
return false;
if (workspace.index () == screen.n_workspaces - 1)
wallpaper.animate (AnimationMode.EASE_OUT_QUAD, 400, opacity : 127);
else
hide_close_button ();
return false;
}
}

View File

@ -1,19 +1,19 @@
//
//
// Copyright (C) 2012 Tom Beckmann, Rico Tzschichholz
//
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//
using Meta;
@ -23,85 +23,72 @@ namespace Gala
{
static const float VIEW_HEIGHT = 140.0f;
static const float SCROLL_SPEED = 30.0f;
Gala.Plugin plugin;
Gala.WindowManager wm;
Screen screen;
Clutter.Actor thumbnails;
Clutter.Actor scroll;
#if !HAS_MUTTER38
Clutter.Actor click_catcher; //invisible plane that catches clicks outside the view
#endif
bool animating; // delay closing the popup
bool wait_one_key_release; //called by shortcut, don't close it on first keyrelease
uint last_switch_time = 0;
Gtk.StyleContext background_style;
Gtk.EventBox background_style_widget;
public WorkspaceView (Gala.Plugin _plugin)
public WorkspaceView (Gala.WindowManager _wm)
{
plugin = _plugin;
screen = plugin.get_screen ();
wm = _wm;
screen = wm.get_screen ();
height = VIEW_HEIGHT;
reactive = true;
clip_to_allocation = true;
background_style_widget = new Gtk.EventBox ();
background_style_widget.show ();
background_style = background_style_widget.get_style_context ();
background_style.add_class ("gala-workspaces-background");
background_style.add_provider (Utils.get_default_style (), Gtk.STYLE_PROVIDER_PRIORITY_FALLBACK);
thumbnails = new Clutter.Actor ();
thumbnails.layout_manager = new Clutter.BoxLayout ();
(thumbnails.layout_manager as Clutter.BoxLayout).spacing = 12;
(thumbnails.layout_manager as Clutter.BoxLayout).homogeneous = true;
content = new Clutter.Canvas ();
(content as Clutter.Canvas).draw.connect (draw_background);
scroll = new Clutter.Actor ();
scroll.height = 12;
scroll.content = new Clutter.Canvas ();
(scroll.content as Clutter.Canvas).draw.connect (draw_scroll);
#if !HAS_MUTTER38
click_catcher = new Clutter.Actor ();
click_catcher.reactive = true;
click_catcher.button_release_event.connect ((e) => {
hide ();
return true;
});
Compositor.get_stage_for_screen (screen).add_child (click_catcher);
#endif
add_child (thumbnails);
add_child (scroll);
//place it somewhere low, so it won't slide down on first open
int swidth, sheight;
screen.get_size (out swidth, out sheight);
y = sheight;
screen.workspace_added.connect ((index) => {
create_workspace_thumb (screen.get_workspace_by_index (index));
});
Prefs.add_listener ((pref) => {
if (pref == Preference.DYNAMIC_WORKSPACES && Prefs.get_dynamic_workspaces ()) {
// if the last workspace has a window, we need to append a new workspace
if (Utils.get_n_windows (screen.get_workspaces ().nth_data (screen.get_n_workspaces () - 1)) > 0)
add_workspace ();
} else if ((pref == Preference.DYNAMIC_WORKSPACES ||
pref == Preference.NUM_WORKSPACES) &&
!Prefs.get_dynamic_workspaces ()) {
// only need to listen for the case when workspaces were removed.
// only need to listen for the case when workspaces were removed.
// Any other case will be caught by the workspace_added signal.
// For some reason workspace_removed is not emitted, when changing the workspace number
if (Prefs.get_num_workspaces () < thumbnails.get_n_children ()) {
@ -111,25 +98,21 @@ namespace Gala
}
}
});
init_thumbnails ();
}
void init_thumbnails ()
{
foreach (var workspace in screen.get_workspaces ()) {
#if HAS_MUTTER38
var thumb = new WorkspaceThumb (workspace, plugin.background_group);
#else
var thumb = new WorkspaceThumb (workspace);
#endif
var thumb = new WorkspaceThumb (workspace, wm.background_group);
thumb.clicked.connect (hide);
thumb.closed.connect (remove_workspace);
thumb.window_on_last.connect (add_workspace);
thumbnails.add_child (thumb);
}
//if there went something wrong, we need to get the system back rolling
if (Prefs.get_dynamic_workspaces ()
&& screen.n_workspaces == 1
@ -137,20 +120,18 @@ namespace Gala
add_workspace ();
}
#if HAS_MUTTER38
bool outside_clicked (Clutter.ButtonEvent event)
{
hide ();
return true;
}
#endif
bool draw_background (Cairo.Context cr)
{
cr.set_operator (Cairo.Operator.CLEAR);
cr.paint ();
cr.set_operator (Cairo.Operator.OVER);
background_style.render_background (cr, 0, 0, width, height);
background_style.render_frame (cr, 0, 0, width, height);
@ -158,78 +139,74 @@ namespace Gala
pat.set_extend (Cairo.Extend.REPEAT);
cr.set_source (pat);
cr.paint_with_alpha (0.6);
return false;
}
bool draw_scroll (Cairo.Context cr)
{
cr.set_operator (Cairo.Operator.CLEAR);
cr.paint ();
cr.set_operator (Cairo.Operator.OVER);
Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, 4, 4, scroll.width-32, 4, 2);
cr.set_source_rgba (1, 1, 1, 0.8);
cr.fill ();
return false;
}
void add_workspace ()
{
var wp = screen.append_new_workspace (false, screen.get_display ().get_current_time ());
if (wp == null)
return;
}
void create_workspace_thumb (Meta.Workspace workspace)
{
#if HAS_MUTTER38
var thumb = new WorkspaceThumb (workspace, plugin.background_group);
#else
var thumb = new WorkspaceThumb (workspace);
#endif
var thumb = new WorkspaceThumb (workspace, wm.background_group);
thumb.clicked.connect (hide);
thumb.closed.connect (remove_workspace);
thumb.window_on_last.connect (add_workspace);
thumbnails.insert_child_at_index (thumb, workspace.index ());
thumb.show ();
check_scrollbar ();
}
void remove_workspace (WorkspaceThumb thumb)
{
//if there's only one used left, remove the second one to avoid rather confusing workspace movement
if (thumb.workspace.index () == 0 && screen.n_workspaces == 2) {
return;
}
thumb.clicked.disconnect (hide);
thumb.closed.disconnect (remove_workspace);
thumb.window_on_last.disconnect (add_workspace);
var workspace = thumb.workspace;
//dont remove non existing workspaces
if (workspace != null && workspace.index () > -1) {
var screen = workspace.get_screen ();
screen.remove_workspace (workspace, screen.get_display ().get_current_time ());
}
thumb.workspace = null;
thumbnails.remove_child (thumb);
thumb.destroy ();
check_scrollbar ();
}
void check_scrollbar ()
{
scroll.visible = thumbnails.width > width;
if (scroll.visible) {
if (thumbnails.x + thumbnails.width < width)
thumbnails.x = width - thumbnails.width;
@ -240,63 +217,41 @@ namespace Gala
thumbnails.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 400, x : width / 2 - thumbnails.width / 2);
}
}
void switch_to_next_workspace (MotionDirection direction)
{
var display = screen.get_display ();
var old_index = screen.get_active_workspace_index ();
var neighbor = screen.get_active_workspace ().get_neighbor (direction);
neighbor.activate (display.get_current_time ());
// if we didnt switch, show a nudge-over animation. need to take the indices
// here since the changing only applies after the animation ends
if (old_index == 0 && direction == MotionDirection.LEFT ||
old_index == screen.n_workspaces - 1 && direction == MotionDirection.RIGHT) {
var dest = (direction == MotionDirection.LEFT ? 32.0f : -32.0f);
Compositor.get_window_group_for_screen (screen).animate (Clutter.AnimationMode.LINEAR, 100, x:dest);
Clutter.Threads.Timeout.add (210, () => {
Compositor.get_window_group_for_screen (screen).animate (Clutter.AnimationMode.LINEAR, 150, x:0.0f);
return false;
});
}
}
public override void key_focus_out ()
{
hide ();
}
public override bool key_press_event (Clutter.KeyEvent event)
{
var display = screen.get_display ();
var current_time = display.get_current_time_roundtrip ();
// Don't allow switching while another animation is still in progress to avoid visual disruptions
if (current_time < (last_switch_time + AnimationSettings.get_default ().workspace_switch_duration))
return false;
int switch_index = -1;
switch (event.keyval) {
case Clutter.Key.Left:
if ((event.modifier_state & Clutter.ModifierType.SHIFT_MASK) != 0)
plugin.move_window (display.get_focus_window (), MotionDirection.LEFT);
wm.move_window (display.get_focus_window (), MotionDirection.LEFT);
else
switch_to_next_workspace (MotionDirection.LEFT);
wm.switch_to_next_workspace (MotionDirection.LEFT);
last_switch_time = current_time;
return false;
case Clutter.Key.Right:
if ((event.modifier_state & Clutter.ModifierType.SHIFT_MASK) != 0)
plugin.move_window (display.get_focus_window (), MotionDirection.RIGHT);
wm.move_window (display.get_focus_window (), MotionDirection.RIGHT);
else
switch_to_next_workspace (MotionDirection.RIGHT);
wm.switch_to_next_workspace (MotionDirection.RIGHT);
last_switch_time = current_time;
return false;
case Clutter.Key.@1:
switch_index = 1;
@ -335,16 +290,16 @@ namespace Gala
default:
break;
}
if (switch_index > 0 && switch_index <= screen.n_workspaces) {
screen.get_workspace_by_index (switch_index - 1).activate (current_time);
last_switch_time = current_time;
}
return true;
}
public override bool key_release_event (Clutter.KeyEvent event)
{
switch (event.keyval) {
@ -360,15 +315,15 @@ namespace Gala
wait_one_key_release = false;
return false;
}
hide ();
return true;
}
return false;
}
public override bool scroll_event (Clutter.ScrollEvent event)
{
switch (event.direction) {
@ -385,12 +340,12 @@ namespace Gala
default:
return false;
}
scroll.x = Math.floorf (width / thumbnails.width * -thumbnails.x);
return false;
}
/*
* if shortcut, wait one key release before closing
*/
@ -400,33 +355,31 @@ namespace Gala
hide ();
return;
}
wait_one_key_release = shortcut;
var screen = plugin.get_screen ();
var screen = wm.get_screen ();
visible = true;
grab_key_focus ();
plugin.begin_modal ();
#if HAS_MUTTER38
plugin.ui_group.button_release_event.connect (outside_clicked);
#endif
wm.begin_modal ();
wm.ui_group.button_release_event.connect (outside_clicked);
var area = screen.get_monitor_geometry (screen.get_primary_monitor ());
y = area.height + area.y;
x = area.x;
width = area.width;
(content as Clutter.Canvas).set_size ((int)width, (int)height);
thumbnails.get_children ().foreach ((thumb) => {
thumb.show ();
});
thumbnails.x = width / 2 - thumbnails.width / 2;
thumbnails.y = 15;
scroll.visible = thumbnails.width > width;
if (scroll.visible) {
scroll.y = height - 12;
@ -434,47 +387,37 @@ namespace Gala
scroll.width = width / thumbnails.width * width;
thumbnails.x = 4.0f;
}
int swidth, sheight;
screen.get_size (out swidth, out sheight);
#if !HAS_MUTTER38
click_catcher.width = swidth;
click_catcher.height = sheight;
click_catcher.x = 0;
click_catcher.y = 0;
click_catcher.visible = true;
#endif
animating = true;
Clutter.Threads.Timeout.add (50, () => {
animating = false;
return false;
}); //catch hot corner hiding problem
var wins = Compositor.get_window_group_for_screen (screen);
wins.detach_animation ();
wins.x = 0.0f;
animate (Clutter.AnimationMode.EASE_OUT_QUAD, 250, y : (area.height + area.y) - height);
wins.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 250, y : -height + 1.01f);
}
public new void hide ()
{
if (!visible || animating)
return;
#if HAS_MUTTER38
plugin.ui_group.button_release_event.disconnect (outside_clicked);
#endif
wm.ui_group.button_release_event.disconnect (outside_clicked);
float width, height;
plugin.get_screen ().get_size (out width, out height);
plugin.end_modal ();
plugin.update_input_area ();
wm.get_screen ().get_size (out width, out height);
wm.end_modal ();
wm.update_input_area ();
animating = true;
animate (Clutter.AnimationMode.EASE_OUT_EXPO, 500, y : height).completed.connect (() => {
thumbnails.get_children ().foreach ((thumb) => {
@ -483,22 +426,11 @@ namespace Gala
animating = false;
visible = false;
});
#if !HAS_MUTTER38
click_catcher.visible = false;
#endif
var wins = Compositor.get_window_group_for_screen (screen);
wins.detach_animation ();
wins.x = 0.0f;
wins.animate (Clutter.AnimationMode.EASE_OUT_EXPO, 500, y : 0.0f);
}
public void handle_switch_to_workspace (Meta.Display display, Meta.Screen screen, Meta.Window? window,
X.Event event, Meta.KeyBinding binding)
{
var direction = (binding.get_name () == "switch-to-workspace-left" ? MotionDirection.LEFT : MotionDirection.RIGHT);
switch_to_next_workspace (direction);
}
}
}

File diff suppressed because it is too large Load Diff

20
vapi/Makefile.am Normal file
View File

@ -0,0 +1,20 @@
VAPIS = \
cogl-fixes.vapi \
config.vapi \
libbamf3.vapi \
gdesktopenums-3.0.vapi \
gnome-desktop-3.0.vapi \
libmutter.vapi \
xfixes-4.0.vapi \
$(NULL)
DEPS = \
libmutter.deps \
gnome-desktop-3.0.deps \
$(NULL)
EXTRA_DIST = \
$(VAPIS) \
$(DEPS) \
$(NULL)

6
vapi/cogl-fixes.vapi Normal file
View File

@ -0,0 +1,6 @@
namespace CoglFixes
{
[CCode (cname = "cogl_texture_get_data")]
public int texture_get_data (Cogl.Texture texture, Cogl.PixelFormat format, uint rowstride, [CCode (array_length = false)] uint8[] pixels);
}

View File

@ -1,5 +1,5 @@
//
// Copyright (C) 2011 Tom Beckmann
// Copyright (C) 2011 Robert Dyer, Rico Tzschichholz
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@ -15,13 +15,14 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
namespace Config {
public const string DATADIR = "@DATADIR@";
public const string PKGDATADIR = "@PKGDATADIR@";
public const string GETTEXT_PACKAGE = "@GETTEXT_PACKAGE@";
public const string RELEASE_NAME = "@RELEASE_NAME@";
public const string VERSION = "@VERSION@";
public const string VERSION_INFO = "@VERSION_INFO@";
public const string PLUGINDIR = "@PLUGINDIR@";
public const string SCHEMA = "org.pantheon.desktop.gala";
[CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "config.h")]
namespace Config
{
public const string DATADIR;
public const string PKGDATADIR;
public const string RELEASE_NAME;
public const string VERSION;
public const string VERSION_INFO;
public const string PLUGINDIR;
public const string SCHEMA;
}

View File

@ -31,10 +31,8 @@ namespace Meta {
#endif
[CCode (cheader_filename = "meta/prefs.h")]
public static bool get_attach_modal_dialogs ();
#if HAS_MUTTER38
[CCode (cheader_filename = "meta/prefs.h")]
public static bool get_auto_maximize ();
#endif
[CCode (cheader_filename = "meta/prefs.h")]
public static bool get_auto_raise ();
[CCode (cheader_filename = "meta/prefs.h")]
@ -69,34 +67,32 @@ namespace Meta {
public static bool get_gnome_animations ();
[CCode (cheader_filename = "meta/prefs.h")]
public static bool get_ignore_request_hide_titlebar ();
#if HAS_MUTTER310
#if HAS_MUTTER310 && !HAS_MUTTER312
[CCode (cheader_filename = "meta/prefs.h")]
public static unowned string get_iso_next_group_option ();
#endif
[CCode (cheader_filename = "meta/prefs.h")]
public static Meta.KeyBindingAction get_keybinding_action (string name);
#if !HAS_MUTTER312
[CCode (cheader_filename = "meta/prefs.h")]
public static GLib.List<weak Meta.KeyPref> get_keybindings ();
[CCode (cheader_filename = "meta/prefs.h")]
#if HAS_MUTTER38
public static int get_mouse_button_menu ();
#else
public static uint get_mouse_button_menu ();
#endif
[CCode (cheader_filename = "meta/prefs.h")]
public static int get_mouse_button_menu ();
[CCode (cheader_filename = "meta/prefs.h")]
public static Meta.VirtualModifier get_mouse_button_mods ();
[CCode (cheader_filename = "meta/prefs.h")]
#if HAS_MUTTER38
public static int get_mouse_button_resize ();
#else
public static uint get_mouse_button_resize ();
#endif
#if !HAS_MUTTER312
[CCode (cheader_filename = "meta/prefs.h")]
public static bool get_no_tab_popup ();
#endif
[CCode (cheader_filename = "meta/prefs.h")]
public static int get_num_workspaces ();
#if !HAS_MUTTER312
[CCode (cheader_filename = "meta/prefs.h")]
public static void get_overlay_binding (Meta.KeyCombo combo);
#endif
[CCode (cheader_filename = "meta/prefs.h")]
public static bool get_raise_on_click ();
[CCode (cheader_filename = "meta/prefs.h")]
@ -123,8 +119,10 @@ namespace Meta {
public static void set_force_fullscreen (bool whether);
[CCode (cheader_filename = "meta/prefs.h")]
public static void set_ignore_request_hide_titlebar (bool whether);
#if !HAS_MUTTER312
[CCode (cheader_filename = "meta/prefs.h")]
public static void set_no_tab_popup (bool whether);
#endif
[CCode (cheader_filename = "meta/prefs.h")]
public static void set_num_workspaces (int n_workspaces);
}
@ -149,10 +147,8 @@ namespace Meta {
public static void error_trap_push (Meta.Display display);
[CCode (cheader_filename = "meta/main.h", cname = "meta_error_trap_push_with_return")]
public static void error_trap_push_with_return (Meta.Display display);
#if HAS_MUTTER38
[CCode (cheader_filename = "meta/main.h", cname = "meta_external_binding_name_for_action")]
public static string external_binding_name_for_action (uint keybinding_action);
#endif
[CCode (cheader_filename = "meta/main.h", cname = "meta_fatal")]
public static void fatal (string format, ...);
[CCode (cheader_filename = "meta/main.h", cname = "meta_free_gslist_and_elements")]
@ -181,22 +177,22 @@ namespace Meta {
public static Meta.Rectangle? rect (int x, int y, int width, int height);
[CCode (cheader_filename = "meta/main.h", cname = "meta_remove_verbose_topic")]
public static void remove_verbose_topic (Meta.DebugTopic topic);
#if !HAS_MUTTER312
[CCode (cheader_filename = "meta/main.h", cname = "meta_set_debugging")]
public static void set_debugging (bool setting);
[CCode (cheader_filename = "meta/main.h", cname = "meta_set_replace_current_wm")]
public static void set_replace_current_wm (bool setting);
#endif
[CCode (cheader_filename = "meta/compositor-mutter.h", cname = "meta_set_stage_input_region")]
public static void set_stage_input_region (Meta.Screen screen, X.XserverRegion region);
#if !HAS_MUTTER312
[CCode (cheader_filename = "meta/main.h", cname = "meta_set_syncing")]
public static void set_syncing (bool setting);
[CCode (cheader_filename = "meta/main.h", cname = "meta_set_verbose")]
public static void set_verbose (bool setting);
[CCode (cheader_filename = "meta/main.h", cname = "meta_show_dialog")]
#if HAS_MUTTER36
public static GLib.Pid show_dialog (string type, string message, string timeout, string display, string ok_text, string cancel_text, string icon_name, int transient_for, GLib.SList<string> columns, GLib.SList<string> entries);
#else
public static GLib.Pid show_dialog (string type, string message, string timeout, string display, string ok_text, string cancel_text, int transient_for, GLib.SList<string> columns, GLib.SList<string> entries);
#endif
[CCode (cheader_filename = "meta/main.h", cname = "meta_show_dialog")]
public static GLib.Pid show_dialog (string type, string message, string timeout, string display, string ok_text, string cancel_text, string icon_name, int transient_for, GLib.SList<string> columns, GLib.SList<string> entries);
[CCode (cheader_filename = "meta/main.h", cname = "meta_topic_real")]
public static void topic_real (Meta.DebugTopic topic, string format, ...);
[CCode (cheader_filename = "meta/main.h", cname = "meta_unsigned_long_equal")]
@ -208,7 +204,6 @@ namespace Meta {
[CCode (cheader_filename = "meta/main.h", cname = "meta_warning")]
public static void warning (string format, ...);
}
#if HAS_MUTTER38
[CCode (cheader_filename = "meta/meta-background.h", type_id = "meta_background_get_type ()")]
public class Background : GLib.Object, Clutter.Content {
[CCode (has_construct_function = false)]
@ -279,34 +274,13 @@ namespace Meta {
public double x;
public double y;
}
#else
[CCode (cheader_filename = "meta/meta-background-actor.h", type_id = "meta_background_actor_get_type ()")]
public class BackgroundActor : Clutter.Actor, Atk.Implementor, Clutter.Animatable, Clutter.Container, Clutter.Scriptable {
[CCode (has_construct_function = false)]
protected BackgroundActor ();
[CCode (has_construct_function = false, type = "ClutterActor*")]
public BackgroundActor.for_screen (Meta.Screen screen);
#if !HAS_MUTTER36
public void add_glsl_snippet (Meta.SnippetHook hook, string declarations, string code, bool is_replace);
public void set_uniform_float (string uniform_name, int n_components, int count, [CCode (array_length_cname = "uniform_length", array_length_pos = 4.1)] float[] uniform);
#endif
[NoAccessorMethod]
public float dim_factor { get; set; }
}
#endif
[CCode (cheader_filename = "meta/compositor.h")]
[Compact]
public class Compositor {
public void add_window (Meta.Window window);
public void destroy ();
#if HAS_MUTTER38
public bool filter_keybinding (Meta.Screen screen, Meta.KeyBinding binding);
#endif
public void flash_screen (Meta.Screen screen);
#if !HAS_MUTTER38
[CCode (cheader_filename = "meta/compositor.h", cname = "meta_get_background_actor_for_screen")]
public static unowned Clutter.Actor? get_background_actor_for_screen (Meta.Screen screen);
#endif
#if !HAS_MUTTER310
[CCode (cheader_filename = "meta/compositor.h", cname = "meta_get_overlay_group_for_screen")]
public static unowned Clutter.Actor? get_overlay_group_for_screen (Meta.Screen screen);
@ -316,27 +290,25 @@ namespace Meta {
#endif
[CCode (cheader_filename = "meta/compositor-mutter.h", cname = "meta_get_stage_for_screen")]
public static unowned Clutter.Actor? get_stage_for_screen (Meta.Screen screen);
#if HAS_MUTTER38
[CCode (cheader_filename = "meta/compositor-mutter.h", cname = "meta_get_top_window_group_for_screen")]
public static unowned Clutter.Actor? get_top_window_group_for_screen (Meta.Screen screen);
#endif
[CCode (cheader_filename = "meta/compositor-mutter.h", cname = "meta_get_window_actors")]
public static unowned GLib.List<weak Meta.WindowActor>? get_window_actors (Meta.Screen screen);
[CCode (cheader_filename = "meta/compositor-mutter.h", cname = "meta_get_window_group_for_screen")]
public static unowned Clutter.Actor? get_window_group_for_screen (Meta.Screen screen);
#if HAS_MUTTER312
public void hide_tile_preview (Meta.Screen screen);
#endif
public void hide_window (Meta.Window window, Meta.CompEffect effect);
public void manage_screen (Meta.Screen screen);
public void maximize_window (Meta.Window window, Meta.Rectangle old_rect, Meta.Rectangle new_rect);
[CCode (cheader_filename = "meta/main.h")]
public static unowned Meta.Compositor @new (Meta.Display display);
#if HAS_MUTTER38
public void queue_frame_drawn (Meta.Window window, bool no_delay_frame);
#endif
public void remove_window (Meta.Window window);
#if HAS_MUTTER38
public void set_updates_frozen (Meta.Window window, bool updates_frozen);
#else
public void set_updates (Meta.Window window, bool updates);
#if HAS_MUTTER312
public void show_tile_preview (Meta.Screen screen, Meta.Window window, Meta.Rectangle tile_rect, int tile_monitor_number);
#endif
public void show_window (Meta.Window window, Meta.CompEffect effect);
#if HAS_MUTTER310
@ -346,19 +318,19 @@ namespace Meta {
public void switch_workspace (Meta.Screen screen, Meta.Workspace from, Meta.Workspace to, Meta.MotionDirection direction);
public void sync_screen_size (Meta.Screen screen, uint width, uint height);
public void sync_stack (Meta.Screen screen, GLib.List<Meta.WindowActor> stack);
#if HAS_MUTTER38
public void sync_window_geometry (Meta.Window window, bool did_placement);
#else
public void sync_window_geometry (Meta.Window window);
#endif
public void unmanage_screen (Meta.Screen screen);
public void unmaximize_window (Meta.Window window, Meta.Rectangle old_rect, Meta.Rectangle new_rect);
#if !HAS_MUTTER312
public void window_mapped (Meta.Window window);
#endif
#if HAS_MUTTER312
public void window_opacity_changed (Meta.Window window);
#endif
public void window_shape_changed (Meta.Window window);
#if !HAS_MUTTER312
public void window_unmapped (Meta.Window window);
#endif
}
#if HAS_MUTTER310
[CCode (cheader_filename = "meta/meta-cursor-tracker.h", type_id = "meta_cursor_tracker_get_type ()")]
@ -378,21 +350,12 @@ namespace Meta {
[CCode (has_construct_function = false)]
protected Display ();
public void add_ignored_crossing_serial (ulong serial);
#if HAS_MUTTER38
public uint add_keybinding (string name, GLib.Settings settings, Meta.KeyBindingFlags flags, owned Meta.KeyHandlerFunc handler);
#else
public bool add_keybinding (string name, GLib.Settings settings, Meta.KeyBindingFlags flags, owned Meta.KeyHandlerFunc handler);
#endif
public bool begin_grab_op (Meta.Screen screen, Meta.Window window, Meta.GrabOp op, bool pointer_already_grabbed, bool frame_action, int button, ulong modmask, uint32 timestamp, int root_x, int root_y);
public void clear_mouse_mode ();
public void end_grab_op (uint32 timestamp);
public void focus_the_no_focus_window (Meta.Screen screen, uint32 timestamp);
#if !HAS_MUTTER38
public X.Atom get_atom (Meta.Atom meta_atom);
#endif
#if HAS_MUTTER38
public void freeze_keyboard (X.Window window, uint32 timestamp);
#endif
public unowned Meta.Compositor get_compositor ();
public void get_compositor_version (int major, int minor);
public uint32 get_current_time ();
@ -401,11 +364,7 @@ namespace Meta {
public unowned Meta.Window get_focus_window ();
public Meta.GrabOp get_grab_op ();
public uint get_ignored_modifier_mask ();
#if HAS_MUTTER38
public uint get_keybinding_action (uint keycode, ulong mask);
#else
public Meta.KeyBindingAction get_keybinding_action (uint keycode, ulong mask);
#endif
public uint32 get_last_user_time ();
public X.Window get_leader_window ();
public unowned GLib.SList<Meta.Screen> get_screens ();
@ -414,10 +373,8 @@ namespace Meta {
public GLib.List<weak Meta.Window> get_tab_list (Meta.TabList type, Meta.Screen screen, Meta.Workspace? workspace);
public unowned Meta.Window get_tab_next (Meta.TabList type, Meta.Screen screen, Meta.Workspace workspace, Meta.Window? window, bool backward);
public unowned X.Display get_xdisplay ();
#if HAS_MUTTER38
public int get_xinput_opcode ();
public uint grab_accelerator (string accelerator);
#endif
public bool has_shape ();
public unowned Meta.Group lookup_group (X.Window group_leader);
public bool remove_keybinding (string name);
@ -428,19 +385,15 @@ namespace Meta {
public void set_input_focus_window (Meta.Window window, bool focus_frame, uint32 timestamp);
public GLib.SList<weak Meta.Window> sort_windows_by_stacking (GLib.SList<Meta.Window> windows);
public bool supports_extended_barriers ();
#if HAS_MUTTER38
public void unfreeze_keyboard (uint32 timestamp);
#endif
public bool ungrab_accelerator (uint action_id);
#if HAS_MUTTER38
public void ungrab_keyboard (uint32 timestamp);
#endif
public void unmanage_screen (Meta.Screen screen, uint32 timestamp);
public bool xserver_time_is_before (uint32 time1, uint32 time2);
public bool xwindow_is_a_no_focus_window (X.Window xwindow);
#if HAS_MUTTER310
public signal void accelerator_activated (uint object, uint p0, uint p1);
#elif HAS_MUTTER38
#else
public signal void accelerator_activated (uint object, uint p0);
#endif
public signal void grab_op_begin (Meta.Screen object, Meta.Window p0, Meta.GrabOp p1);
@ -487,19 +440,13 @@ namespace Meta {
public uint get_mask ();
public Meta.VirtualModifier get_modifiers ();
public unowned string get_name ();
#if HAS_MUTTER38
public bool is_builtin ();
#endif
[CCode (cheader_filename = "meta/keybindings.h", cname = "meta_keybindings_set_custom_handler")]
public static bool set_custom_handler (string name, owned Meta.KeyHandlerFunc? handler);
#if !HAS_MUTTER312
[CCode (cheader_filename = "meta/keybindings.h", cname = "meta_keybindings_switch_window")]
public static void switch_window (Meta.Display display, Meta.Screen screen, Meta.Window event_window, X.Event event, Meta.KeyBinding binding);
#endif
}
[CCode (cheader_filename = "meta/main.h")]
[Compact]
public class KeyHandler {
}
[CCode (cheader_filename = "meta/meta-plugin.h", type_id = "meta_plugin_get_type ()")]
public abstract class Plugin : GLib.Object {
@ -519,17 +466,17 @@ namespace Meta {
public void end_modal (uint32 timestamp);
public unowned Meta.PluginInfo? get_info ();
public unowned Meta.Screen get_screen ();
#if HAS_MUTTER38
#if HAS_MUTTER312
[NoWrapper]
public virtual void hide_tile_preview ();
#endif
[NoWrapper]
public virtual bool keybinding_filter (Meta.KeyBinding binding);
#endif
[NoWrapper]
public virtual void kill_switch_workspace ();
[NoWrapper]
public virtual void kill_window_effects (Meta.WindowActor actor);
#if HAS_MUTTER36
public static void manager_set_plugin_type (GLib.Type gtype);
#endif
[NoWrapper]
public virtual void map (Meta.WindowActor actor);
public void map_completed (Meta.WindowActor actor);
@ -542,14 +489,15 @@ namespace Meta {
[NoWrapper]
public virtual unowned Meta.PluginInfo? plugin_info ();
public bool running ();
#if HAS_MUTTER312
[NoWrapper]
public virtual void show_tile_preview (Meta.Window window, Meta.Rectangle tile_rect, int tile_monitor_number);
#endif
[NoWrapper]
public virtual void start ();
[NoWrapper]
public virtual void switch_workspace (int from, int to, Meta.MotionDirection direction);
public void switch_workspace_completed ();
#if !HAS_MUTTER36
public static void type_register (GLib.Type plugin_type);
#endif
[NoWrapper]
public virtual void unmaximize (Meta.WindowActor actor, int x, int y, int width, int height);
public void unmaximize_completed (Meta.WindowActor actor);
@ -567,9 +515,7 @@ namespace Meta {
[CCode (has_construct_function = false)]
protected Screen ();
public unowned Meta.Workspace? append_new_workspace (bool activate, uint32 timestamp);
#if HAS_MUTTER38
public void focus_default_window (uint32 timestamp);
#endif
public static unowned Meta.Screen? for_x_screen (X.Screen xscreen);
public unowned Meta.Workspace get_active_workspace ();
public int get_active_workspace_index ();
@ -579,10 +525,8 @@ namespace Meta {
#endif
public unowned Meta.Display get_display ();
public Meta.Rectangle get_monitor_geometry (int monitor);
#if HAS_MUTTER38
public bool get_monitor_in_fullscreen (int monitor);
public int get_monitor_index_for_rect (Meta.Rectangle rect);
#endif
public int get_n_monitors ();
public int get_n_workspaces ();
public int get_primary_monitor ();
@ -604,9 +548,7 @@ namespace Meta {
[NoAccessorMethod]
public bool keyboard_grabbed { get; }
public int n_workspaces { get; }
#if HAS_MUTTER38
public signal void in_fullscreen_changed ();
#endif
public signal void monitors_changed ();
public signal void restacked ();
public signal void startup_sequence_changed (void* object);
@ -628,14 +570,15 @@ namespace Meta {
}
[CCode (cheader_filename = "meta/meta-shaped-texture.h", type_id = "meta_shaped_texture_get_type ()")]
public class ShapedTexture : Clutter.Actor, Atk.Implementor, Clutter.Animatable, Clutter.Container, Clutter.Scriptable {
#if HAS_MUTTER312
[CCode (has_construct_function = false)]
protected ShapedTexture ();
#else
[CCode (has_construct_function = false, type = "ClutterActor*")]
public ShapedTexture ();
public Cairo.Surface get_image (Cairo.RectangleInt clip);
#if HAS_MUTTER38
public unowned Cogl.Texture get_texture ();
#else
public unowned Cogl.Handle get_texture ();
#endif
public Cairo.Surface get_image (Cairo.RectangleInt clip);
public unowned Cogl.Texture get_texture ();
#if !HAS_MUTTER312
#if HAS_MUTTER310
public void set_clip_region (Cairo.Region clip_region);
@ -647,20 +590,14 @@ namespace Meta {
#if HAS_MUTTER312
public void set_input_shape_region (Cairo.Region shape_region);
#endif
#if HAS_MUTTER38
public void set_mask_texture (Cogl.Texture mask_texture);
#else
public void set_mask_texture (Cogl.Handle mask_texture);
#endif
#if HAS_MUTTER310
public void set_opaque_region (owned Cairo.Region opaque_region);
#endif
#if !HAS_MUTTER312
public void set_pixmap (X.Pixmap pixmap);
#if HAS_MUTTER312
public void update_area (int x, int y, int width, int height, Cairo.Region unobscured_region);
#else
public void update_area (int x, int y, int width, int height);
#endif
public void update_area (int x, int y, int width, int height);
}
[CCode (cheader_filename = "meta/theme.h")]
[Compact]
@ -686,9 +623,18 @@ namespace Meta {
protected Window ();
public void activate (uint32 current_time);
public void activate_with_workspace (uint32 current_time, Meta.Workspace workspace);
#if HAS_MUTTER312
public bool allows_move ();
public bool allows_resize ();
#endif
public void begin_grab_op (Meta.GrabOp op, bool frame_action, uint32 timestamp);
#if HAS_MUTTER310
public bool can_close ();
#endif
#if HAS_MUTTER312
public bool can_maximize ();
public bool can_minimize ();
public bool can_shade ();
#endif
public void change_workspace (Meta.Workspace workspace);
#if HAS_MUTTER312
@ -696,9 +642,7 @@ namespace Meta {
#else
public void change_workspace_by_index (int space_index, bool append, uint32 timestamp);
#endif
#if HAS_MUTTER38
public void check_alive (uint32 timestamp);
#endif
#if HAS_MUTTER312
public Meta.Rectangle client_rect_to_frame_rect (Meta.Rectangle client_rect);
#endif
@ -712,10 +656,8 @@ namespace Meta {
#if HAS_MUTTER312
public Meta.Rectangle frame_rect_to_client_rect (Meta.Rectangle frame_rect);
#endif
#if HAS_MUTTER38
[CCode (array_length_pos = 0.1, array_length_type = "gsize")]
public int[] get_all_monitors ();
#endif
public unowned string get_client_machine ();
public unowned GLib.Object get_compositor_private ();
public unowned string get_description ();
@ -756,37 +698,35 @@ namespace Meta {
public X.Atom get_window_type_atom ();
public unowned string get_wm_class ();
public unowned string get_wm_class_instance ();
#if HAS_MUTTER38
public Meta.Rectangle get_work_area_all_monitors ();
public Meta.Rectangle get_work_area_current_monitor ();
public Meta.Rectangle get_work_area_for_monitor (int which_monitor);
#endif
public unowned Meta.Workspace get_workspace ();
public X.Window get_xwindow ();
public void group_leader_changed ();
public bool has_focus ();
#if HAS_MUTTER312
public bool is_above ();
public bool is_always_on_all_workspaces ();
#endif
public bool is_ancestor_of_transient (Meta.Window transient);
public bool is_attached_dialog ();
public bool is_fullscreen ();
public bool is_hidden ();
#if !HAS_MUTTER312
public bool is_mapped ();
public bool is_modal ();
#if HAS_MUTTER38
public bool is_monitor_sized ();
#endif
public bool is_modal ();
public bool is_monitor_sized ();
public bool is_on_all_workspaces ();
public bool is_on_primary_monitor ();
public bool is_override_redirect ();
public bool is_remote ();
#if HAS_MUTTER38
public bool is_screen_sized ();
#endif
public bool is_shaded ();
public bool is_skip_taskbar ();
public void kill ();
#if HAS_MUTTER38
public bool located_on_workspace (Meta.Workspace workspace);
#endif
public void lower ();
public void make_above ();
public void make_fullscreen ();
@ -797,21 +737,25 @@ namespace Meta {
public void move_resize_frame (bool user_op, int root_x_nw, int root_y_nw, int w, int h);
public void move_to_monitor (int monitor);
public void raise ();
#if HAS_MUTTER38
public bool requested_bypass_compositor ();
public bool requested_dont_bypass_compositor ();
#endif
public void resize (bool user_op, int w, int h);
public void set_compositor_private (GLib.Object priv);
public void set_demands_attention ();
#if HAS_MUTTER38
public void set_icon_geometry (Meta.Rectangle? rect);
#endif
public void shade (uint32 timestamp);
#if HAS_MUTTER312
public void shove_titlebar_onscreen ();
#endif
public bool showing_on_its_workspace ();
public void shutdown_group ();
public void stick ();
#if HAS_MUTTER312
public bool titlebar_is_onscreen ();
#endif
#if !HAS_MUTTER312
public bool toplevel_is_mapped ();
#endif
public void unmake_above ();
public void unmake_fullscreen ();
public void unmaximize (Meta.MaximizeFlags directions);
@ -860,16 +804,18 @@ namespace Meta {
public string wm_class { get; }
[CCode (cname = "focus")]
public signal void focused ();
#if HAS_MUTTER312
public signal void position_changed ();
#endif
public signal void raised ();
#if HAS_MUTTER312
public signal void size_changed ();
#endif
public signal void unmanaged ();
public signal void workspace_changed (int object);
}
[CCode (cheader_filename = "meta/meta-window-actor.h", type_id = "meta_window_actor_get_type ()")]
#if HAS_MUTTER38
public class WindowActor : Clutter.Actor, Atk.Implementor, Clutter.Animatable, Clutter.Container, Clutter.Scriptable {
#else
public class WindowActor : Clutter.Group, Atk.Implementor, Clutter.Animatable, Clutter.Container, Clutter.Scriptable {
#endif
[CCode (has_construct_function = false)]
protected WindowActor ();
#if !HAS_MUTTER310
@ -890,8 +836,10 @@ namespace Meta {
public bool no_shadow { get; set; }
[NoAccessorMethod]
public string shadow_class { owned get; set; }
#if !HAS_MUTTER312
public signal void position_changed ();
public signal void size_changed ();
#endif
}
[CCode (cheader_filename = "meta/main.h")]
[Compact]
@ -906,9 +854,7 @@ namespace Meta {
public unowned Meta.Workspace get_neighbor (Meta.MotionDirection direction);
public unowned Meta.Screen get_screen ();
public Meta.Rectangle get_work_area_all_monitors ();
#if HAS_MUTTER38
public Meta.Rectangle get_work_area_for_monitor (int which_monitor);
#endif
public int index ();
public GLib.List<weak Meta.Window> list_windows ();
public void set_builtin_struts (GLib.SList<Meta.Strut> struts);
@ -942,6 +888,7 @@ namespace Meta {
public Gtk.Border total;
public void clear ();
}
#if !HAS_MUTTER312
[CCode (cheader_filename = "meta/prefs.h", has_type_id = false)]
public struct KeyCombo {
public uint keysym;
@ -958,6 +905,7 @@ namespace Meta {
public bool per_window;
public bool builtin;
}
#endif
[CCode (cheader_filename = "meta/meta-plugin.h", has_type_id = false)]
public struct PluginInfo {
public weak string name;
@ -1002,7 +950,6 @@ namespace Meta {
public Meta.Rectangle rect;
public Meta.Side side;
}
#if HAS_MUTTER38
[CCode (cheader_filename = "meta/meta-background.h", cprefix = "META_BACKGROUND_EFFECTS_", type_id = "meta_background_effects_get_type ()")]
[Flags]
public enum BackgroundEffects {
@ -1017,12 +964,6 @@ namespace Meta {
NEGATIVE_X,
NEGATIVE_Y
}
#else
[CCode (cheader_filename = "meta/display.h", cprefix = "META_ATOM_", type_id = "meta_atom_get_type ()")]
public enum Atom {
FIRST
}
#endif
[CCode (cheader_filename = "meta/common.h", cprefix = "META_BUTTON_FUNCTION_", type_id = "meta_button_function_get_type ()")]
public enum ButtonFunction {
MENU,
@ -1182,6 +1123,7 @@ namespace Meta {
KEYBOARD_RESIZING_NE,
KEYBOARD_RESIZING_SW,
KEYBOARD_RESIZING_NW,
#if !HAS_MUTTER312
KEYBOARD_TABBING_NORMAL,
KEYBOARD_TABBING_DOCK,
KEYBOARD_ESCAPING_NORMAL,
@ -1189,6 +1131,7 @@ namespace Meta {
KEYBOARD_ESCAPING_GROUP,
KEYBOARD_TABBING_GROUP,
KEYBOARD_WORKSPACE_SWITCHING,
#endif
CLICKING_MINIMIZE,
CLICKING_MAXIMIZE,
CLICKING_UNMAXIMIZE,
@ -1228,10 +1171,8 @@ namespace Meta {
WORKSPACE_RIGHT,
WORKSPACE_UP,
WORKSPACE_DOWN,
#if HAS_MUTTER38
SWITCH_APPLICATIONS,
SWITCH_APPLICATIONS_BACKWARD,
#endif
SWITCH_GROUP,
SWITCH_GROUP_BACKWARD,
SWITCH_WINDOWS,
@ -1244,8 +1185,10 @@ namespace Meta {
CYCLE_WINDOWS_BACKWARD,
CYCLE_PANELS,
CYCLE_PANELS_BACKWARD,
#if !HAS_MUTTER312
TAB_POPUP_SELECT,
TAB_POPUP_CANCEL,
#endif
SHOW_DESKTOP,
PANEL_MAIN_MENU,
PANEL_RUN_DIALOG,
@ -1322,11 +1265,9 @@ namespace Meta {
[CCode (cheader_filename = "meta/util.h", cprefix = "META_LATER_", type_id = "meta_later_type_get_type ()")]
public enum LaterType {
RESIZE,
#if HAS_MUTTER38
CALC_SHOWING,
CHECK_FULLSCREEN,
SYNC_STACK,
#endif
BEFORE_REDRAW,
IDLE
}
@ -1334,7 +1275,12 @@ namespace Meta {
[Flags]
public enum MaximizeFlags {
HORIZONTAL,
#if HAS_MUTTER312
VERTICAL,
BOTH
#else
VERTICAL
#endif
}
[CCode (cheader_filename = "meta/common.h", cprefix = "META_MENU_OP_", type_id = "meta_menu_op_get_type ()")]
[Flags]
@ -1411,13 +1357,11 @@ namespace Meta {
EDGE_TILING,
FORCE_FULLSCREEN,
WORKSPACES_ONLY_ON_PRIMARY,
#if !HAS_MUTTER312
NO_TAB_POPUP,
#if HAS_MUTTER38
#endif
DRAGGABLE_BORDER_WIDTH,
AUTO_MAXIMIZE;
#else
DRAGGABLE_BORDER_WIDTH;
#endif
[CCode (cheader_filename = "meta/main.h")]
public static unowned string to_string (Meta.Preference pref);
}
@ -1435,17 +1379,6 @@ namespace Meta {
TOP,
BOTTOM
}
#if !HAS_MUTTER36
[CCode (cheader_filename = "meta/main.h", cprefix = "META_SNIPPET_HOOK_", type_id = "meta_snippet_hook_get_type ()")]
public enum SnippetHook {
VERTEX,
VERTEX_TRANSFORM,
FRAGMENT,
TEXTURE_COORD_TRANSFORM,
LAYER_FRAGMENT,
TEXTURE_LOOKUP
}
#endif
[CCode (cheader_filename = "meta/common.h", cprefix = "META_LAYER_", type_id = "meta_stack_layer_get_type ()")]
public enum StackLayer {
DESKTOP,
@ -1533,12 +1466,10 @@ namespace Meta {
public const int PRIORITY_REDRAW;
[CCode (cheader_filename = "meta/main.h", cname = "META_PRIORITY_RESIZE")]
public const int PRIORITY_RESIZE;
#if HAS_MUTTER38
[CCode (cheader_filename = "meta/main.h", cname = "META_VIRTUAL_CORE_KEYBOARD_ID")]
public const int VIRTUAL_CORE_KEYBOARD_ID;
[CCode (cheader_filename = "meta/main.h", cname = "META_VIRTUAL_CORE_POINTER_ID")]
public const int VIRTUAL_CORE_POINTER_ID;
#endif
[CCode (cheader_filename = "meta/main.h")]
public static void exit (Meta.ExitCode code);
[CCode (cheader_filename = "meta/main.h")]
@ -1549,10 +1480,8 @@ namespace Meta {
public static void init ();
[CCode (cheader_filename = "meta/main.h")]
public static void quit (Meta.ExitCode code);
#if HAS_MUTTER38
[CCode (cheader_filename = "meta/main.h")]
public static void register_with_session ();
#endif
[CCode (cheader_filename = "meta/main.h")]
public static int run ();
[CCode (cheader_filename = "meta/main.h")]