muffin-2.8.4/0000775000175000017500000000000012623653707011750 5ustar fabiofabiomuffin-2.8.4/README-Mutter0000664000175000017500000004123312623653707014111 0ustar fabiofabioMetacity is not a meta-City as in an urban center, but rather Meta-ness as in the state of being meta. i.e. metacity : meta as opacity : opaque. Also it may have something to do with the Meta key on UNIX keyboards. The first release of Metacity was version 2.3. Metacity has no need for your petty hangups about version numbers. The stable releases so far are 2.4.x, 2.6.x, 2.8.[01], 2.8.1.x, 2.8.5-, 2.10.x, 2.12.x, 2.14.x, 2.16.x. Unstable branches are 2.3.x, 2.5.x, 2.8.2-4, 2.9.x, 2.11.x, 2.13.x, 2.15.x, 2.17.x. COMPILING MUFFIN === You need GTK+ 2.2. For startup notification to work you need libstartup-notification at http://www.freedesktop.org/software/startup-notification/ or on the GNOME ftp site. You need Clutter 1.0. You need gobject-introspection 0.6.3. REPORTING BUGS AND SUBMITTING PATCHES === Report new bugs on http://bugzilla.gnome.org. Please check for duplicates, *especially* if you are reporting a feature request. Please do *not* add "me too!" or "yes I really want this!" comments to feature requests in bugzilla. Please read http://pobox.com/~hp/features.html prior to adding any kind of flame about missing features or misfeatures. Feel free to send patches too; Metacity is relatively small and simple, so if you find a bug or want to add a feature it should be pretty easy. Send me mail, or put the patch in bugzilla. See the HACKING file for some notes on hacking Muffin. MUFFIN FEATURES === - Uses GTK+ 2.0 for drawing window frames. This means colors, fonts, etc. come from GTK+ theme. - Does not expose the concept of "window manager" to the user. Some of the features in the GNOME control panel and other parts of the desktop happen to be implemented in metacity, such as changing your window border theme, or changing your window navigation shortcuts, but the user doesn't need to know this. - Includes only the window manager; does not try to be a desktop environment. The pager, configuration, etc. are all separate and modular. The "libwnck" library (which I also wrote) is available for writing metacity extensions, pagers, and so on. (But libwnck isn't metacity specific, or GNOME-dependent; it requires only GTK, and should work with KWin, fvwm2, and other EWMH-compliant WMs.) - Has a simple theme system and a couple of extra themes come with it. Change themes via gsettings: gsettings set org.cinnamon.desktop.wm.preferences theme Crux gsettings set org.cinnamon.desktop.wm.preferences theme Gorilla gsettings set org.cinnamon.desktop.wm.preferences theme Atlanta gsettings set org.cinnamon.desktop.wm.preferences theme Bright See theme-format.txt for docs on the theme format. Use metacity-theme-viewer to preview themes. - Change number of workspaces via gsettings: gsettings set org.cinnamon.desktop.wm.preferences num-workspaces 5 Can also change workspaces from GNOME 2 pager. - Change focus mode: gsettings set org.cinnamon.desktop.wm.preferences focus-mode mouse gsettings set org.cinnamon.desktop.wm.preferences focus-mode sloppy gsettings set org.cinnamon.desktop.wm.preferences focus-mode click - Global keybinding defaults include: Alt-Tab forward cycle window focus Alt-Shift-Tab backward cycle focus Alt-Ctrl-Tab forward cycle focus among panels Alt-Ctrl-Shift-Tab backward cycle focus among panels Alt-Escape cycle window focus without a popup thingy Ctrl-Alt-Left Arrow previous workspace Ctrl-Alt-Right Arrow next workspace Ctrl-Alt-D minimize/unminimize all, to show desktop Change keybindings for example: gsettings set org.cinnamon.desktop.wm.keybindings switch-to-workspace-1 '[F1]' Also try the GNOME keyboard shortcuts control panel. - Window keybindings: Alt-space window menu Mnemonics work in the menu. That is, Alt-space then underlined letter in the menu item works. Choose Move from menu, and arrow keys to move the window. While moving, hold down Control to move slower, and Shift to snap to edges. Choose Resize from menu, and nothing happens yet, but eventually I might implement something. Keybindings for things like maximize window, vertical maximize, etc. can be bound, but may not all exist by default. See metacity.schemas. - Window mouse bindings: Clicking anywhere on frame with button 1 will raise/focus window If you click a window control, such as the close button, then the control will activate on button release if you are still over it on release (as with most GUI toolkits) If you click and drag borders with button 1 it resizes the window If you click and drag the titlebar with button 1 it moves the window. If you click anywhere on the frame with button 2 it lowers the window. If you click anywhere on the frame with button 3 it shows the window menu. If you hold down Super (windows key) and click inside a window, it will move the window (buttons 1 and 2) or show menu (button 3). Or you can configure a different modifier for this. If you pick up a window with button 1 and then switch workspaces the window will come with you to the new workspace, this is a feature copied from Enlightenment. If you hold down Shift while moving a window, the window snaps to edges of other windows and the screen. - Session management: Muffin connects to the session manager and will set itself up to be respawned. It theoretically restores sizes/positions/workspace for session-aware applications. - Muffin implements much of the EWMH window manager specification from freedesktop.org, as well as the older ICCCM. Please refer to the COMPLIANCE file for information on muffin compliance with these standards. - Uses Pango to render text, so has cool i18n capabilities. Supports UTF-8 window titles and such. - There are simple animations for actions such as minimization, to help users see what is happening. Should probably have a few more of these and make them nicer. - if you have the proper X setup, set the GDK_USE_XFT=1 environment variable to get antialiased window titles. - considers the panel when placing windows and maximizing them. - handles the window manager selection from the ICCCM. Will exit if another WM claims it, and can claim it from another WM if you pass the --replace argument. So if you're running another ICCCM-compliant WM, you can run "muffin --replace" to replace it with Metacity. - does basic colormap handling - and much more! well, maybe not a lot more. HOW TO ADD EXTERNAL FEATURES === You can write a muffin "plugin" such as a pager, window list, icon box, task menu, or even things like "window matching" using the Extended Window Manager Hints. See http://www.freedesktop.org for the EWMH specification. An easy-to-use library called "libwnck" is available that uses the EWMH and is specifically designed for writing WM accessories. You might be interested in existing accessories such as "Devil's Pie" by Ross Burton, which add features to Muffin (or other EWMH-compliant WMs). MUFFIN BUGS, NON-FEATURES, AND CAVEATS === See bugzilla: http://bugzilla.gnome.org/query.cgi FAQ === Q: Will you add my feature? A: If it makes sense to turn on unconditionally, or is genuinely a harmless preference that I would not be embarrassed to put in a simple, uncluttered, user-friendly configuration dialog. If the only rationale for your feature is that other window managers have it, or that you are personally used to it, or something like that, then I will not be impressed. Metacity is firmly in the "choose good defaults" camp rather than the "offer 6 equally broken ways to do it, and let the user pick one" camp. This is part of a "no crackrock" policy, despite some exceptions I'm mildly embarrassed about. For example, multiple workspaces probably constitute crackrock, they confuse most users and really are not that useful if you have a decent tasklist and so on. But I am too used to them to turn them off. Or alternatively iconification/tasklist is crack, and workspaces/pager are good. But having both is certainly a bit wrong. Sloppy focus is probably crackrock too. But don't think unlimited crack is OK just because I slipped up a little. No slippery slope here. Don't let this discourage patches and fixes - I love those. ;-) Just be prepared to hear the above objections if your patch adds some crack-ridden configuration option. http://pobox.com/~hp/free-software-ui.html http://pobox.com/~hp/features.html Q: Will Muffin be part of GNOME? A: It is not officially part of GNOME as of GNOME 2.27. We are hoping to have muffin officially included as of GNOME 2.28. Q: Why does Muffin remember the workspace/position of some apps but not others across logout/login? A: Muffin only stores sizes/positions for apps that are session managed. As far as I can determine, there is no way to attempt to remember workspace/position for non-session-aware apps without causing a lot of weird effects. The reason is that you don't know which non-SM-aware apps were launched by the session. When you initially log in, Metacity sees a bunch of new windows appear. But it can't distinguish between windows that were stored in your session, or windows you just launched after logging in. If Metacity tried to guess that a window was from the session, it could e.g. end up maximizing a dialog, or put a window you just launched on another desktop or in a weird place. And in fact I see a lot of bugs like this in window managers that try to handle non-session-aware apps. However, for session-aware apps, Muffin can tell that the application instance is from the session and thus restore it reliably, assuming the app properly restores the windows it had open on session save. So the correct way to fix the situation is to make apps session-aware. libSM has come with X for years, it's very standardized, it's shared by GNOME and KDE - even twm is session-aware. So anyone who won't take a patch to add SM is more archaic than twm - and you should flame them. ;-) Docs on session management: http://www.fifi.org/doc/xspecs/xsmp.txt.gz http://www.fifi.org/doc/xspecs/SMlib.txt.gz See also the ICCCM section on SM. For GNOME apps, use the GnomeClient object. For a simple example of using libSM directly, twm/session.c in the twm source code is pretty easy to understand. Q: How about adding viewports in addition to workspaces? A: I could conceivably be convinced to use viewports _instead_ of workspaces, though currently I'm not thinking that. But I don't think it makes any sense to have both; it's just confusing. They are functionally equivalent. You may think this means that you won't have certain keybindings, or something like that. This is a misconception. The only _fundamental_ difference between viewports and workspaces is that with viewports, windows can "overlap" and appear partially on one and partially on another. All other differences that traditionally exist in other window managers are accidental - the features commonly associated with viewports can be implemented for workspaces, and vice versa. So I don't want to have two kinds of workspace/desktop/viewport/whatever, but I'm willing to add features traditionally associated with either kind if those features make sense. Q: Why is the panel always on top? A: Because it's a better user interface, and until we made this not configurable a bunch of apps were not getting fixed (the app authors were just saying "put your panel on the bottom" instead of properly supporting fullscreen mode, and such). rationales.txt has the bugzilla URL for some flamefesting on this, if you want to go back and relive the glory. Read these and the bugzilla stuff before asking/commenting: http://pobox.com/~hp/free-software-ui.html http://pobox.com/~hp/features.html Q: Why is there no edge flipping? A: This one is also in rationales.txt. Because "ouija board" UI, where you just move the mouse around and the computer guesses what you mean, has a lot of issues. This includes mouse focus, shade-hover mode, edge flipping, autoraise, etc. Metacity has mouse focus and autoraise as a compromise, but these features are all confusing for many users, and cause problems with accessibility, fitt's law, and so on. Read these and the bugzilla stuff before asking/commenting: http://pobox.com/~hp/free-software-ui.html http://pobox.com/~hp/features.html Q: Why does wireframe move/resize suck? A: You can turn it on with the reduced_resources setting. But: it has low usability, and is a pain to implement, and there's no reason opaque move/resize should be a problem on any setup that can run a modern desktop worth a darn to begin with. Read these and the bugzilla stuff before asking/commenting: http://pobox.com/~hp/free-software-ui.html http://pobox.com/~hp/features.html The reason we had to add wireframe anyway was broken proprietary apps that can't handle lots of resize events. Q: Why no XYZ? A: You are probably getting the idea by now - check rationales.txt, query/search bugzilla, and read http://pobox.com/~hp/features.html and http://pobox.com/~hp/free-software-ui.html Then sit down and answer the question for yourself. Is the feature good? What's the rationale for it? Answer "why" not just "why not." Justify in terms of users as a whole, not just users like yourself. How else can you solve the same problem? etc. If that leads you to a strong opinion, then please, post the rationale for discussion to an appropriate bugzilla bug, or to usability@gnome.org. Please don't just "me too!" on bugzilla bugs, please don't think flames will get you anywhere, and please don't repeat rationale that's already been offered. Q: Your dumb web pages you made me read talk about solving problems in fundamental ways instead of adding preferences or workarounds. What are some examples where metacity has done this? A: There are quite a few, though many opportunities remain. Sometimes the real fix involves application changes. The metacity approach is that it's OK to require apps to change, though there are also plenty of workarounds in metacity for battles considered too hard to fight. Here are some examples: - fullscreen mode was introduced to allow position constraints, panel-on-top, and other such things to apply to normal windows while still allowing video players etc. to "just work" - "whether to include minimized windows in Alt+Tab" was solved by putting minimized windows at the *end* of the tab order. - Whether to pop up a feedback display during Alt+Tab was solved by having both Alt+Tab and Alt+Esc - Whether to have a "kill" feature was solved by automatically detecting and offering to kill stuck apps. Better, metacity actually does "kill -9" on the process, it doesn't just disconnect the process from the X server. You'll appreciate this if you ever did a "kill" on Netscape 4, and watched it keep eating 100% CPU even though the X server had booted it. - The workspaces vs. viewports mess was avoided by adding directional navigation and such to workspaces, see discussion earlier in this file. - Instead of configurable placement algorithms, there's just one that works fairly well most of the time. - To avoid excess CPU use during opaque move/resize, we rate limit the updates to the application window's size. - Instead of configurable "show size of window while resizing," it's only shown for windows where it matters, such as terminals. (Only use-case given for all windows is for web designers choosing their web browser size, but there are web sites and desktop backgrounds that do this for you.) - Using startup notification, applications open on the workspace where you launched them, not the active workspace when their window is opened. - and much more. Q: I think muffin sucks. A: Feel free to use any WM you like. The reason metacity follows the ICCCM and EWMH specifications is that it makes metacity a modular, interchangeable part in the desktop. libwnck-based apps such as the GNOME window list will work just fine with any EWMH-compliant WM. Q: Did you spend a lot of time on this? A: Originally the answer was no. Sadly the answer is now yes. Q: How can you claim that you are anti-crack, while still writing a window manager? A: I have no comment on that. muffin-2.8.4/COPYING0000664000175000017500000004311312623653707013005 0ustar fabiofabio GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) 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 this service 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 make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. 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. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), 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 distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the 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 a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE 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. 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 convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision 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, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This 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 Library General Public License instead of this License. muffin-2.8.4/debian/0000775000175000017500000000000012623653707013172 5ustar fabiofabiomuffin-2.8.4/configure.ac0000664000175000017500000003733012623653707014244 0ustar fabiofabioAC_PREREQ(2.50) m4_define([muffin_major_version], [2]) m4_define([muffin_minor_version], [8]) m4_define([muffin_micro_version], [4]) m4_define([muffin_version], [muffin_major_version.muffin_minor_version.muffin_micro_version]) m4_define([muffin_plugin_api_version], [3]) AC_INIT([muffin], [muffin_version], [https://github.com/linuxmint/muffin/issues]) AC_CONFIG_SRCDIR(src/core/display.c) AC_CONFIG_HEADERS(config.h) AC_CONFIG_MACRO_DIR(m4) AM_INIT_AUTOMAKE([1.11 no-dist-gzip dist-xz tar-ustar subdir-objects]) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],) AM_MAINTAINER_MODE([enable]) MUFFIN_MAJOR_VERSION=muffin_major_version MUFFIN_MINOR_VERSION=muffin_minor_version MUFFIN_MICRO_VERSION=muffin_micro_version MUFFIN_PLUGIN_API_VERSION=muffin_plugin_api_version AC_SUBST(MUFFIN_MAJOR_VERSION) AC_SUBST(MUFFIN_MINOR_VERSION) AC_SUBST(MUFFIN_MICRO_VERSION) AC_SUBST(MUFFIN_PLUGIN_API_VERSION) MUFFIN_PLUGIN_DIR="$libdir/$PACKAGE/plugins" AC_SUBST(MUFFIN_PLUGIN_DIR) # Honor aclocal flags AC_SUBST(ACLOCAL_AMFLAGS, "\${ACLOCAL_FLAGS}") GETTEXT_PACKAGE=muffin AC_SUBST(GETTEXT_PACKAGE) AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Name of default gettext domain]) IT_PROG_INTLTOOL([0.34.90]) AC_PROG_CC AM_PROG_CC_C_O AC_ISC_POSIX AC_HEADER_STDC AC_LIBTOOL_WIN32_DLL AM_PROG_LIBTOOL # Sets GLIB_GENMARSHAL and GLIB_MKENUMS AM_PATH_GLIB_2_0() #### Integer sizes AC_CHECK_SIZEOF(char) AC_CHECK_SIZEOF(short) AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(void *) AC_CHECK_SIZEOF(long long) AC_CHECK_SIZEOF(__int64) ## byte order AC_C_BIGENDIAN #### Usability of visibility attributes gl_VISIBILITY AC_DEFINE(LOCAL_SYMBOL, [], [attribute of the non-exported symbols]) AC_DEFINE(API_EXPORTED, [], [attribute of the symbols exported in the API]) if test $HAVE_VISIBILITY = 1; then AC_DEFINE(LOCAL_SYMBOL, [__attribute__ ((visibility ("hidden")))]) AC_DEFINE(API_EXPORTED, [__attribute__ ((visibility ("default")))]) fi CANBERRA_GTK=libcanberra-gtk3 CANBERRA_GTK_VERSION=0.26 CLUTTER_PACKAGE=clutter-1.0 MUFFIN_PC_MODULES=" gtk+-3.0 >= 3.9.12 gio-2.0 >= 2.25.10 pango >= 1.14.0 cairo >= 1.10.0 cinnamon-desktop >= 2.4.0 xcomposite >= 0.3 xfixes xrender xdamage $CLUTTER_PACKAGE >= 1.14.3 cogl-1.0 >= 1.13.3 gl " GLIB_GSETTINGS AC_ARG_ENABLE(verbose-mode, AC_HELP_STRING([--disable-verbose-mode], [disable muffin's ability to do verbose logging, for embedded/size-sensitive custom builds]),, enable_verbose_mode=yes) if test x$enable_verbose_mode = xyes; then AC_DEFINE(WITH_VERBOSE_MODE,1,[Build with verbose mode support]) fi AC_ARG_ENABLE([gtk-doc], AC_HELP_STRING([--enable-gtk-doc], [use gtk-doc to build documentation [[default=yes]]]),, enable_gtk_doc=yes) AC_ARG_ENABLE(sm, AC_HELP_STRING([--disable-sm], [disable muffin's session management support, for embedded/size-sensitive custom non-GNOME builds]),, enable_sm=auto) AC_ARG_ENABLE(startup-notification, AC_HELP_STRING([--disable-startup-notification], [disable muffin's startup notification support, for embedded/size-sensitive custom non-GNOME builds]),, enable_startup_notification=auto) AC_ARG_WITH(libcanberra, AC_HELP_STRING([--without-libcanberra], [disable the use of libcanberra for playing sounds]),, with_libcanberra=auto) AC_ARG_ENABLE(xsync, AC_HELP_STRING([--disable-xsync], [disable muffin's use of the XSync extension]),, enable_xsync=auto) AC_ARG_ENABLE(shape, AC_HELP_STRING([--disable-shape], [disable muffin's use of the shaped window extension]),, enable_shape=auto) ## try definining HAVE_BACKTRACE AC_CHECK_HEADERS(execinfo.h, [AC_CHECK_FUNCS(backtrace)]) AM_GLIB_GNU_GETTEXT ## here we get the flags we'll actually use PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.37.3) PKG_CHECK_MODULES(MUFFIN_MESSAGE, gtk+-3.0) PKG_CHECK_MODULES(MUFFIN_WINDOW_DEMO, gtk+-3.0) # Unconditionally use this dir to avoid a circular dep with gnomecc GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings" AC_SUBST(GNOME_KEYBINDINGS_KEYSDIR) STARTUP_NOTIFICATION_VERSION=0.7 AC_MSG_CHECKING([Startup notification library >= $STARTUP_NOTIFICATION_VERSION]) if $PKG_CONFIG --atleast-version $STARTUP_NOTIFICATION_VERSION libstartup-notification-1.0; then have_startup_notification=yes else have_startup_notification=no fi AC_MSG_RESULT($have_startup_notification) if test x$enable_startup_notification = xyes; then have_startup_notification=yes echo "startup-notification support forced on" elif test x$enable_startup_notification = xauto; then true else have_startup_notification=no fi if test x$have_startup_notification = xyes; then echo "Building with libstartup-notification" MUFFIN_PC_MODULES="$MUFFIN_PC_MODULES libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_VERSION" AC_DEFINE(HAVE_STARTUP_NOTIFICATION, , [Building with startup notification support]) else echo "Building without libstartup-notification" fi have_libcanberra=no AC_MSG_CHECKING([libcanberra-gtk]) if test x$with_libcanberra = xno ; then AC_MSG_RESULT([disabled]) else if $PKG_CONFIG --exists $CANBERRA_GTK '>=' $CANBERRA_GTK_VERSION; then have_libcanberra=yes AC_MSG_RESULT(yes) MUFFIN_PC_MODULES="$MUFFIN_PC_MODULES $CANBERRA_GTK" AC_DEFINE([HAVE_LIBCANBERRA], 1, [Building with libcanberra for playing sounds]) else AC_MSG_RESULT(no) if test x$with_libcanberra = xyes ; then AC_MSG_ERROR([libcanberra forced and libcanberra-gtk was not found]) fi fi fi INTROSPECTION_VERSION=0.9.2 GOBJECT_INTROSPECTION_CHECK([$INTROSPECTION_VERSION]) if test x$found_introspection != xno; then AC_DEFINE(HAVE_INTROSPECTION, 1, [Define if GObject introspection is available]) MUFFIN_PC_MODULES="$MUFFIN_PC_MODULES gobject-introspection-1.0" # Since we don't make any guarantees about stability and we don't support # parallel install, there's no real reason to change directories, filenames, # etc. as we change the Muffin tarball version. Note that this must match # api_version in src/Makefile.am # This is set to a magic number which is different from the API which # Mutter uses. Otherwise there will be dependency conflicts in RPM # based distributions that automatically resolve typelib file dependencies. META_GIR=Meta_Muffin_0_gir # META_GIR=[Meta_]muffin_major_version[_]muffin_minor_version[_gir] AC_SUBST(META_GIR) fi AC_MSG_CHECKING([Xcursor]) if $PKG_CONFIG xcursor; then have_xcursor=yes else have_xcursor=no fi AC_MSG_RESULT($have_xcursor) if test x$have_xcursor = xyes; then echo "Building with Xcursor" MUFFIN_PC_MODULES="$MUFFIN_PC_MODULES xcursor" AC_DEFINE(HAVE_XCURSOR, , [Building with Xcursor support]) fi PKG_CHECK_MODULES(MUFFIN, $MUFFIN_PC_MODULES) # This is used for plugins AC_SUBST(CLUTTER_PACKAGE) PKG_CHECK_MODULES(CLUTTER, $CLUTTER_PACKAGE) AC_PATH_XTRA ALL_X_LIBS="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS" # Check for Xinerama extension (Solaris impl or Xfree impl) muffin_save_cppflags="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $X_CFLAGS" AC_ARG_ENABLE(xinerama, AC_HELP_STRING([--disable-xinerama], [disable muffin's use of the Xinerama extension]), try_xinerama=$enable_xinerama,try_xinerama=yes) use_solaris_xinerama=no use_xfree_xinerama=no if test "${try_xinerama}" != no; then case "$host" in *-*-solaris*) # Check for solaris use_solaris_xinerama=yes AC_CHECK_LIB(Xext, XineramaGetInfo, use_solaris_xinerama=yes, use_solaris_xinerama=no, $ALL_X_LIBS) if test "x$use_solaris_xinerama" = "xyes"; then AC_CHECK_HEADER(X11/extensions/xinerama.h, if test -z "`echo $ALL_X_LIBS | grep "\-lXext" 2> /dev/null`"; then X_EXTRA_LIBS="-lXext $X_EXTRA_LIBS" fi AC_DEFINE(HAVE_SOLARIS_XINERAMA, , [Have Solaris-style Xinerama]) AC_DEFINE(HAVE_XINERAMA, , [Have some version of Xinerama]), use_solaris_xinerama=no, [#include ]) fi AC_MSG_CHECKING(for Xinerama support on Solaris) AC_MSG_RESULT($use_solaris_xinerama); ;; *) # Check for XFree use_xfree_xinerama=yes AC_CHECK_LIB(Xinerama, XineramaQueryExtension, [AC_CHECK_HEADER(X11/extensions/Xinerama.h, X_EXTRA_LIBS="-lXinerama $X_EXTRA_LIBS" if test -z "`echo $ALL_X_LIBS | grep "\-lXext" 2> /dev/null`"; then X_EXTRA_LIBS="-lXext $X_EXTRA_LIBS" fi AC_DEFINE(HAVE_XFREE_XINERAMA, , [Have XFree86-style Xinerama]) AC_DEFINE(HAVE_XINERAMA,, [Have some version of Xinerama]), use_xfree_xinerama=no, [#include ])], use_xfree_xinerama=no, -lXext $ALL_X_LIBS) AC_MSG_CHECKING(for Xinerama support on XFree86) AC_MSG_RESULT($use_xfree_xinerama); ;; esac fi CPPFLAGS="$muffin_save_cppflags" SHAPE_LIBS= found_shape=no AC_CHECK_LIB(Xext, XShapeQueryExtension, [AC_CHECK_HEADER(X11/extensions/shape.h, SHAPE_LIBS=-lXext found_shape=yes)], , $ALL_X_LIBS) if test x$enable_shape = xno; then found_shape=no fi if test x$enable_shape = xyes; then if test "$found_shape" = "no"; then AC_MSG_ERROR([--enable-shape forced and Shape not found]) exit 1 fi fi if test "x$found_shape" = "xyes"; then AC_DEFINE(HAVE_SHAPE, , [Have the shape extension library]) fi found_xkb=no AC_CHECK_LIB(X11, XkbQueryExtension, [AC_CHECK_HEADER(X11/XKBlib.h, found_xkb=yes)], , $ALL_X_LIBS) if test "x$found_xkb" = "xyes"; then AC_DEFINE(HAVE_XKB, , [Have keyboard extension library]) fi RANDR_LIBS= found_randr=no AC_CHECK_LIB(Xrandr, XRRUpdateConfiguration, [AC_CHECK_HEADER(X11/extensions/Xrandr.h, RANDR_LIBS=-lXrandr found_randr=yes,, [#include ])], , -lXrender -lXext $ALL_X_LIBS) if test "x$found_randr" = "xyes"; then AC_DEFINE(HAVE_RANDR, , [Have the Xrandr extension library]) fi XSYNC_LIBS= found_xsync=no AC_CHECK_LIB(Xext, XSyncQueryExtension, [AC_CHECK_HEADER(X11/extensions/sync.h, found_xsync=yes,, [#include ])], , $ALL_X_LIBS) if test x$enable_xsync = xno; then found_xsync=no fi if test x$enable_xsync = xyes; then if test "$found_xsync" = "no"; then AC_MSG_ERROR([--enable-xsync forced and XSync not found]) exit 1 fi fi if test "x$found_xsync" = "xyes"; then XSYNC_LIBS=-lXext AC_DEFINE(HAVE_XSYNC, , [Have the Xsync extension library]) fi MUFFIN_LIBS="$MUFFIN_LIBS $XSYNC_LIBS $RANDR_LIBS $SHAPE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm" MUFFIN_MESSAGE_LIBS="$MUFFIN_MESSAGE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS" MUFFIN_WINDOW_DEMO_LIBS="$MUFFIN_WINDOW_DEMO_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm" MUFFIN_PROPS_LIBS="$MUFFIN_PROPS_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS" found_sm=no case "$MUFFIN_LIBS" in *-lSM*) found_sm=yes ;; *) AC_CHECK_LIB(SM, SmcSaveYourselfDone, [AC_CHECK_HEADERS(X11/SM/SMlib.h, MUFFIN_LIBS="-lSM -lICE $MUFFIN_LIBS" found_sm=yes)], , $MUFFIN_LIBS) ;; esac if test x$enable_sm = xno; then found_sm=no fi if test x$enable_sm = xyes; then if test "$found_sm" = "no"; then AC_MSG_ERROR([--enable-sm forced and -lSM not found]) exit 1 fi fi if test "$found_sm" = "yes"; then AC_DEFINE(HAVE_SM, , [Building with SM support]) fi AM_CONDITIONAL(HAVE_SM, test "$found_sm" = "yes") HOST_ALIAS=$host_alias AC_SUBST(HOST_ALIAS) AC_PATH_PROG(GDK_PIXBUF_CSOURCE, gdk-pixbuf-csource, no) if test x"$GDK_PIXBUF_CSOURCE" = xno; then AC_MSG_ERROR([gdk-pixbuf-csource executable not found in your path - should be installed with GTK]) fi AC_SUBST(GDK_PIXBUF_CSOURCE) AC_PATH_PROG(ZENITY, zenity, no) if test x"$ZENITY" = xno; then AC_MSG_ERROR([zenity not found in your path - needed for dialogs]) fi AC_ARG_ENABLE(debug, [ --enable-debug enable debugging],, enable_debug=no) if test "x$enable_debug" = "xyes"; then CFLAGS="$CFLAGS -g -O" fi # For fix-meta-rectangle.py AM_PATH_PYTHON([2.5]) # Use gnome-doc-utils: GNOME_DOC_INIT([0.8.0]) GTK_DOC_CHECK([1.15], [--flavour no-tmpl]) AC_CHECK_DECL([GL_EXT_x11_sync_object], [], [AC_MSG_ERROR([GL_EXT_x11_sync_object definition not found, please update your GL headers])], [#include ]) #### Warnings (last since -Werror can disturb other tests) # Stay command-line compatible with the gnome-common configure option. Here # minimum/yes/maximum are the same, however. AC_ARG_ENABLE(compile_warnings, AS_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],[Turn on compiler warnings]),, enable_compile_warnings=yes) changequote(,)dnl if test "$enable_compile_warnings" != no ; then if test "x$GCC" = "xyes"; then case " $CFLAGS " in *[\ \ ]-Wall[\ \ ]*) ;; *) CFLAGS="$CFLAGS -Wall" ;; esac # case " $CFLAGS " in # *[\ \ ]-Wshadow[\ \ ]*) ;; # *) CFLAGS="$CFLAGS -Wshadow" ;; # esac case " $CFLAGS " in *[\ \ ]-Wchar-subscripts[\ \ ]*) ;; *) CFLAGS="$CFLAGS -Wchar-subscripts" ;; esac case " $CFLAGS " in *[\ \ ]-Wmissing-declarations[\ \ ]*) ;; *) CFLAGS="$CFLAGS -Wmissing-declarations" ;; esac case " $CFLAGS " in *[\ \ ]-Wmissing-prototypes[\ \ ]*) ;; *) CFLAGS="$CFLAGS -Wmissing-prototypes" ;; esac case " $CFLAGS " in *[\ \ ]-Wnested-externs[\ \ ]*) ;; *) CFLAGS="$CFLAGS -Wnested-externs" ;; esac case " $CFLAGS " in *[\ \ ]-Wpointer-arith[\ \ ]*) ;; *) CFLAGS="$CFLAGS -Wpointer-arith" ;; esac case " $CFLAGS " in *[\ \ ]-Wsign-compare[\ \ ]*) ;; *) CFLAGS="$CFLAGS -Wsign-compare" ;; esac if test "$enable_compile_warnings" = error; then case " $CFLAGS " in *[\ \ ]-Werror[\ \ ]*) ;; *) CFLAGS="$CFLAGS -Werror -Wno-error=deprecated-declarations" ;; esac fi fi fi changequote([,])dnl AC_CONFIG_FILES([ Makefile data/Makefile doc/Makefile doc/man/Makefile doc/reference/Makefile doc/reference/muffin-docs.sgml src/Makefile src/wm-tester/Makefile src/libmuffin.pc src/muffin-plugins.pc src/tools/Makefile src/compositor/plugins/Makefile po/Makefile.in ]) AC_OUTPUT if test x$enable_verbose_mode = xno; then echo "*** WARNING WARNING WARNING WARNING WARNING" echo "*** Building without verbose mode" echo "*** This means there's no way to debug muffin problems." echo "*** Please build normal desktop versions of muffin" echo "*** with verbose mode enabled so users can use it when they report bugs." fi dnl ========================================================================== echo " muffin-$VERSION prefix: ${prefix} source code location: ${srcdir} compiler: ${CC} XFree86 Xinerama: ${use_xfree_xinerama} Solaris Xinerama: ${use_solaris_xinerama} Startup notification: ${have_startup_notification} libcanberra: ${have_libcanberra} Introspection: ${found_introspection} Session management: ${found_sm} Shape extension: ${found_shape} Xsync: ${found_xsync} Xcursor: ${have_xcursor} " muffin-2.8.4/src/0000775000175000017500000000000012623653707012537 5ustar fabiofabiomuffin-2.8.4/src/muffin-enum-types.h.in0000664000175000017500000000101412623653707016701 0ustar fabiofabio/*** BEGIN file-header ***/ #ifndef __MUFFIN_ENUM_TYPES_H__ #define __MUFFIN_ENUM_TYPES_H__ #include G_BEGIN_DECLS /*** END file-header ***/ /*** BEGIN file-production ***/ /* enumerations from "@filename@" */ /*** END file-production ***/ /*** BEGIN file-tail ***/ G_END_DECLS #endif /* !__MUFFIN_ENUM_TYPES_H__ */ /*** END file-tail ***/ /*** BEGIN value-header ***/ GType @enum_name@_get_type (void) G_GNUC_CONST; #define META_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) /*** END value-header ***/ muffin-2.8.4/src/stock_delete.png0000664000175000017500000000033412623653707015712 0ustar fabiofabioPNG  IHDRabKGD pHYs  tIME,tEXtCommentCreated with The GIMPd%n@IDAT8c`v?-τG!1b 2io0\`UDi RH#S9 IENDB`muffin-2.8.4/src/muffin.desktop.desktop0000664000175000017500000000075312623653707017073 0ustar fabiofabio [Desktop Entry] Type=Application Name=Muffin Exec=muffin NoDisplay=true # name of loadable control center module X-GNOME-WMSettingsModule=metacity # name we put on the WM spec check window X-GNOME-WMName=Muffin # back compat only X-GnomeWMSettingsLibrary=metacity X-GNOME-Bugzilla-Bugzilla=GNOME X-GNOME-Bugzilla-Product=muffin X-GNOME-Bugzilla-Component=general X-GNOME-Autostart-Phase=WindowManager X-GNOME-Provides=windowmanager X-GNOME-Autostart-Notify=true Name[en_US]=muffin.desktop muffin-2.8.4/src/tools/0000775000175000017500000000000012623653707013677 5ustar fabiofabiomuffin-2.8.4/src/tools/muffin-mag.c0000664000175000017500000002011612623653707016071 0ustar fabiofabio/* Hack for use instead of xmag */ /* * Copyright (C) 2002 Red Hat 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #define _XOPEN_SOURCE 600 /* C99 -- for rint() */ #include #include #include #include #include #include static GtkWidget *grab_widget = NULL; static GtkWidget *display_window = NULL; static int last_grab_x = 0; static int last_grab_y = 0; static int last_grab_width = 150; static int last_grab_height = 150; static GtkAllocation last_grab_allocation; static double width_factor = 4.0; static double height_factor = 4.0; static GdkInterpType interp_mode = GDK_INTERP_NEAREST; static guint regrab_idle_id = 0; static GdkPixbuf* get_pixbuf (void) { GdkPixbuf *screenshot; GdkPixbuf *magnified; #if 0 g_print ("Size %d x %d\n", last_grab_width, last_grab_height); #endif screenshot = gdk_pixbuf_get_from_window (gdk_get_default_root_window (), last_grab_x, last_grab_y, last_grab_width, last_grab_height); if (screenshot == NULL) { g_printerr ("Screenshot failed\n"); exit (1); } magnified = gdk_pixbuf_scale_simple (screenshot, last_grab_width * width_factor, last_grab_height * height_factor, interp_mode); g_object_unref (G_OBJECT (screenshot)); return magnified; } static gboolean regrab_idle (GtkWidget *image) { GtkAllocation allocation; GdkPixbuf *magnified; gtk_widget_get_allocation (image, &allocation); if (allocation.width != last_grab_allocation.width || allocation.height != last_grab_allocation.height) { last_grab_width = rint (allocation.width / width_factor); last_grab_height = rint (allocation.height / height_factor); last_grab_allocation = allocation; magnified = get_pixbuf (); gtk_image_set_from_pixbuf (GTK_IMAGE (image), magnified); g_object_unref (G_OBJECT (magnified)); } regrab_idle_id = 0; return FALSE; } static void image_resized (GtkWidget *image) { if (regrab_idle_id == 0) regrab_idle_id = g_idle_add_full (G_PRIORITY_LOW + 100, (GSourceFunc) regrab_idle, image, NULL); } static void grab_area_at_mouse (GtkWidget *invisible, int x_root, int y_root) { GdkPixbuf *magnified; int width, height; GtkWidget *widget; width = last_grab_width; height = last_grab_height; last_grab_x = x_root; last_grab_y = y_root; last_grab_width = width; last_grab_height = height; magnified = get_pixbuf (); display_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size (GTK_WINDOW (display_window), last_grab_width, last_grab_height); widget = gtk_image_new_from_pixbuf (magnified); gtk_widget_set_size_request (widget, 40, 40); gtk_container_add (GTK_CONTAINER (display_window), widget); g_object_unref (G_OBJECT (magnified)); g_object_add_weak_pointer (G_OBJECT (display_window), (gpointer) &display_window); g_signal_connect (G_OBJECT (display_window), "destroy", G_CALLBACK (gtk_main_quit), NULL); g_signal_connect_after (G_OBJECT (widget), "size_allocate", G_CALLBACK (image_resized), NULL); gtk_widget_show_all (display_window); } static void shutdown_grab (void) { GdkDeviceManager *manager; GdkDevice *device; manager = gdk_display_get_device_manager (gdk_display_get_default ()); device = gdk_device_manager_get_client_pointer (manager); gdk_device_ungrab (device, gtk_get_current_event_time ()); gdk_device_ungrab (gdk_device_get_associated_device (device), gtk_get_current_event_time ()); gtk_grab_remove (grab_widget); } static void mouse_motion (GtkWidget *invisible, GdkEventMotion *event, gpointer data) { } static gboolean mouse_release (GtkWidget *invisible, GdkEventButton *event, gpointer data) { if (event->button != 1) return FALSE; grab_area_at_mouse (invisible, event->x_root, event->y_root); shutdown_grab (); g_signal_handlers_disconnect_by_func (invisible, mouse_motion, NULL); g_signal_handlers_disconnect_by_func (invisible, mouse_release, NULL); return TRUE; } /* Helper Functions */ static gboolean mouse_press (GtkWidget *invisible, GdkEventButton *event, gpointer data); static gboolean key_press (GtkWidget *invisible, GdkEventKey *event, gpointer data) { if (event->keyval == GDK_KEY_Escape) { shutdown_grab (); g_signal_handlers_disconnect_by_func (invisible, mouse_press, NULL); g_signal_handlers_disconnect_by_func (invisible, key_press, NULL); gtk_main_quit (); return TRUE; } return FALSE; } static gboolean mouse_press (GtkWidget *invisible, GdkEventButton *event, gpointer data) { if (event->type == GDK_BUTTON_PRESS && event->button == 1) { g_signal_connect (invisible, "motion_notify_event", G_CALLBACK (mouse_motion), NULL); g_signal_connect (invisible, "button_release_event", G_CALLBACK (mouse_release), NULL); g_signal_handlers_disconnect_by_func (invisible, mouse_press, NULL); g_signal_handlers_disconnect_by_func (invisible, key_press, NULL); return TRUE; } return FALSE; } static void begin_area_grab (void) { GdkWindow *window; GdkDeviceManager *manager; GdkDevice *device; if (grab_widget == NULL) { grab_widget = gtk_invisible_new (); gtk_widget_add_events (grab_widget, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK); gtk_widget_show (grab_widget); } window = gtk_widget_get_window (grab_widget); manager = gdk_display_get_device_manager (gdk_display_get_default ()); device = gdk_device_manager_get_client_pointer (manager); if (gdk_device_grab (device, window, GDK_OWNERSHIP_NONE, FALSE, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK, NULL, gtk_get_current_event_time ()) != GDK_GRAB_SUCCESS) { g_warning ("Failed to grab pointer to do eyedropper"); return; } if (gdk_device_grab (gdk_device_get_associated_device (device), window, GDK_OWNERSHIP_NONE, FALSE, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK, NULL, gtk_get_current_event_time ()) != GDK_GRAB_SUCCESS) { gdk_device_ungrab (device, gtk_get_current_event_time ()); g_warning ("Failed to grab keyboard to do eyedropper"); return; } gtk_grab_add (grab_widget); g_signal_connect (grab_widget, "button_press_event", G_CALLBACK (mouse_press), NULL); g_signal_connect (grab_widget, "key_press_event", G_CALLBACK (key_press), NULL); } int main (int argc, char **argv) { gtk_init (&argc, &argv); begin_area_grab (); gtk_main (); return 0; } muffin-2.8.4/src/tools/muffin-window-demo.c0000664000175000017500000007266012623653707017571 0ustar fabiofabio/* Muffin window types/properties demo app */ /* * Copyright (C) 2002 Havoc Pennington * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #include #include #include #include static GtkWidget* do_appwindow (void); static gboolean aspect_on; static void set_gdk_window_struts (GdkWindow *window, int left, int right, int top, int bottom) { long vals[12]; vals[0] = left; vals[1] = right; vals[2] = top; vals[3] = bottom; vals[4] = 000; vals[5] = 400; vals[6] = 200; vals[7] = 600; vals[8] = 76; vals[9] = 676; vals[10] = 200; vals[11] = 800; XChangeProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window), XInternAtom (GDK_WINDOW_XDISPLAY (window), "_NET_WM_STRUT_PARTIAL", False), XA_CARDINAL, 32, PropModeReplace, (guchar *)vals, 12); } static void on_realize_set_struts (GtkWindow *window, gpointer data) { GtkWidget *widget; int left; int right; int top; int bottom; widget = GTK_WIDGET (window); g_return_if_fail (gtk_widget_get_realized (widget)); left = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "meta-strut-left")); right = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "meta-strut-right")); top = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "meta-strut-top")); bottom = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "meta-strut-bottom")); set_gdk_window_struts (gtk_widget_get_window (widget), left, right, top, bottom); } static void set_gtk_window_struts (GtkWidget *window, int left, int right, int top, int bottom) { GtkWidget *widget; widget = GTK_WIDGET (window); g_object_set_data (G_OBJECT (window), "meta-strut-left", GINT_TO_POINTER (left)); g_object_set_data (G_OBJECT (window), "meta-strut-right", GINT_TO_POINTER (right)); g_object_set_data (G_OBJECT (window), "meta-strut-top", GINT_TO_POINTER (top)); g_object_set_data (G_OBJECT (window), "meta-strut-bottom", GINT_TO_POINTER (bottom)); g_signal_handlers_disconnect_by_func (G_OBJECT (window), on_realize_set_struts, NULL); g_signal_connect_after (G_OBJECT (window), "realize", G_CALLBACK (on_realize_set_struts), NULL); if (gtk_widget_get_realized (widget)) set_gdk_window_struts (gtk_widget_get_window (widget), left, right, top, bottom); } static void set_gdk_window_type (GdkWindow *window, const char *type) { Atom atoms[2] = { None, None }; atoms[0] = XInternAtom (GDK_WINDOW_XDISPLAY (window), type, False); XChangeProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window), XInternAtom (GDK_WINDOW_XDISPLAY (window), "_NET_WM_WINDOW_TYPE", False), XA_ATOM, 32, PropModeReplace, (guchar *)atoms, 1); } static void on_realize_set_type (GtkWindow *window, gpointer data) { GtkWidget *widget; const char *type; widget = GTK_WIDGET (window); g_return_if_fail (gtk_widget_get_realized (widget)); type = g_object_get_data (G_OBJECT (window), "meta-window-type"); g_return_if_fail (type != NULL); set_gdk_window_type (gtk_widget_get_window (widget), type); } static void set_gtk_window_type (GtkWindow *window, const char *type) { GtkWidget *widget; widget = GTK_WIDGET (window); g_object_set_data (G_OBJECT (window), "meta-window-type", (char*) type); g_signal_handlers_disconnect_by_func (G_OBJECT (window), on_realize_set_type, NULL); g_signal_connect_after (G_OBJECT (window), "realize", G_CALLBACK (on_realize_set_type), NULL); if (gtk_widget_get_realized (widget)) set_gdk_window_type (gtk_widget_get_window (widget), type); } static void set_gdk_window_border_only (GdkWindow *window) { gdk_window_set_decorations (window, GDK_DECOR_BORDER); } static void on_realize_set_border_only (GtkWindow *window, gpointer data) { GtkWidget *widget; widget = GTK_WIDGET (window); g_return_if_fail (gtk_widget_get_realized (widget)); set_gdk_window_border_only (gtk_widget_get_window (widget)); } static void set_gtk_window_border_only (GtkWindow *window) { GtkWidget *widget; widget = GTK_WIDGET (window); g_signal_handlers_disconnect_by_func (G_OBJECT (window), on_realize_set_border_only, NULL); g_signal_connect_after (G_OBJECT (window), "realize", G_CALLBACK (on_realize_set_border_only), NULL); if (gtk_widget_get_realized (widget)) set_gdk_window_border_only (gtk_widget_get_window (widget)); } int main (int argc, char **argv) { GList *list; GdkPixbuf *pixbuf; GError *err; gtk_init (&argc, &argv); err = NULL; pixbuf = gdk_pixbuf_new_from_file (MUFFIN_ICON_DIR"/muffin-window-demo.png", &err); if (pixbuf) { list = g_list_prepend (NULL, pixbuf); gtk_window_set_default_icon_list (list); g_list_free (list); g_object_unref (G_OBJECT (pixbuf)); } else { g_printerr ("Could not load icon: %s\n", err->message); g_error_free (err); } do_appwindow (); gtk_main (); return 0; } static void response_cb (GtkDialog *dialog, int response_id, void *data); static void make_dialog (GtkWidget *parent, int depth) { GtkWidget *dialog; char *str; dialog = gtk_message_dialog_new (parent ? GTK_WINDOW (parent) : NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, parent ? "Here is a dialog %d" : "Here is a dialog %d with no transient parent", depth); str = g_strdup_printf ("%d dialog", depth); gtk_window_set_title (GTK_WINDOW (dialog), str); g_free (str); gtk_dialog_add_button (GTK_DIALOG (dialog), "Open child dialog", GTK_RESPONSE_ACCEPT); /* Close dialog on user response */ g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (response_cb), NULL); g_object_set_data (G_OBJECT (dialog), "depth", GINT_TO_POINTER (depth)); gtk_widget_show (dialog); } static void response_cb (GtkDialog *dialog, int response_id, void *data) { switch (response_id) { case GTK_RESPONSE_ACCEPT: make_dialog (GTK_WIDGET (dialog), GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), "depth")) + 1); break; default: gtk_widget_destroy (GTK_WIDGET (dialog)); break; } } static void dialog_cb (GtkAction *action, gpointer callback_data) { make_dialog (GTK_WIDGET (callback_data), 1); } static void modal_dialog_cb (GtkAction *action, gpointer callback_data) { GtkWidget *dialog; dialog = gtk_message_dialog_new (GTK_WINDOW (callback_data), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "Here is a MODAL dialog"); set_gtk_window_type (GTK_WINDOW (dialog), "_NET_WM_WINDOW_TYPE_MODAL_DIALOG"); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); } static void no_parent_dialog_cb (GtkAction *action, gpointer callback_data) { make_dialog (NULL, 1); } static void utility_cb (GtkAction *action, gpointer callback_data) { GtkWidget *window; GtkWidget *vbox; GtkWidget *button; window = gtk_window_new (GTK_WINDOW_TOPLEVEL); set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_UTILITY"); gtk_window_set_title (GTK_WINDOW (window), "Utility"); gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (callback_data)); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_container_add (GTK_CONTAINER (window), vbox); button = gtk_button_new_with_mnemonic ("_A button"); gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); button = gtk_button_new_with_mnemonic ("_B button"); gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); button = gtk_button_new_with_mnemonic ("_C button"); gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); button = gtk_button_new_with_mnemonic ("_D button"); gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); gtk_widget_show_all (window); } static void toolbar_cb (GtkAction *action, gpointer callback_data) { GtkWidget *window; GtkWidget *vbox; GtkWidget *label; window = gtk_window_new (GTK_WINDOW_TOPLEVEL); set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_TOOLBAR"); gtk_window_set_title (GTK_WINDOW (window), "Toolbar"); gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (callback_data)); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_container_add (GTK_CONTAINER (window), vbox); label = gtk_label_new ("FIXME this needs a resize grip, etc."); gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); gtk_widget_show_all (window); } static void menu_cb (GtkAction *action, gpointer callback_data) { GtkWidget *window; GtkWidget *vbox; GtkWidget *label; window = gtk_window_new (GTK_WINDOW_TOPLEVEL); set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_MENU"); gtk_window_set_title (GTK_WINDOW (window), "Menu"); gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (callback_data)); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_container_add (GTK_CONTAINER (window), vbox); label = gtk_label_new ("FIXME this isn't a menu."); gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); gtk_widget_show_all (window); } static void override_redirect_cb (GtkAction *action, gpointer callback_data) { GtkWidget *window; GtkWidget *vbox; GtkWidget *label; window = gtk_window_new (GTK_WINDOW_POPUP); gtk_window_set_title (GTK_WINDOW (window), "Override Redirect"); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_container_add (GTK_CONTAINER (window), vbox); label = gtk_label_new ("This is an override\nredirect window\nand should not be managed"); gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); gtk_widget_show_all (window); } static void border_only_cb (GtkAction *action, gpointer callback_data) { GtkWidget *window; GtkWidget *vbox; GtkWidget *label; window = gtk_window_new (GTK_WINDOW_TOPLEVEL); set_gtk_window_border_only (GTK_WINDOW (window)); gtk_window_set_title (GTK_WINDOW (window), "Border only"); gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (callback_data)); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_container_add (GTK_CONTAINER (window), vbox); label = gtk_label_new ("This window is supposed to have a border but no titlebar."); gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); gtk_widget_show_all (window); } #if 0 static void changing_icon_cb (GtkAction *action, gpointer callback_data) { GtkWidget *window; GtkWidget *vbox; GtkWidget *label; window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (window), "Changing Icon"); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_container_add (GTK_CONTAINER (window), vbox); label = gtk_label_new ("This window has an icon that changes over time"); gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); gtk_widget_show_all (window); } #endif static gboolean focus_in_event_cb (GtkWidget *window, GdkEvent *event, gpointer data) { GtkWidget *widget; widget = GTK_WIDGET (data); gtk_label_set_text (GTK_LABEL (widget), "Has focus"); return TRUE; } static gboolean focus_out_event_cb (GtkWidget *window, GdkEvent *event, gpointer data) { GtkWidget *widget; widget = GTK_WIDGET (data); gtk_label_set_text (GTK_LABEL (widget), "Not focused"); return TRUE; } static GtkWidget* focus_label (GtkWidget *window) { GtkWidget *label; label = gtk_label_new ("Not focused"); g_signal_connect (G_OBJECT (window), "focus_in_event", G_CALLBACK (focus_in_event_cb), label); g_signal_connect (G_OBJECT (window), "focus_out_event", G_CALLBACK (focus_out_event_cb), label); return label; } static void splashscreen_cb (GtkAction *action, gpointer callback_data) { GtkWidget *window; GtkWidget *image; GtkWidget *vbox; window = gtk_window_new (GTK_WINDOW_TOPLEVEL); set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_SPLASHSCREEN"); gtk_window_set_title (GTK_WINDOW (window), "Splashscreen"); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG); gtk_box_pack_start (GTK_BOX (vbox), image, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), focus_label (window), FALSE, FALSE, 0); gtk_container_add (GTK_CONTAINER (window), vbox); gtk_widget_show_all (window); } enum { DOCK_TOP = 1, DOCK_BOTTOM = 2, DOCK_LEFT = 3, DOCK_RIGHT = 4, DOCK_ALL = 5 }; static void make_dock (int type) { GtkWidget *window; GtkWidget *image; GtkWidget *box; GtkWidget *button; g_return_if_fail (type != DOCK_ALL); box = NULL; switch (type) { case DOCK_LEFT: case DOCK_RIGHT: box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); break; case DOCK_TOP: case DOCK_BOTTOM: box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); break; case DOCK_ALL: break; } window = gtk_window_new (GTK_WINDOW_TOPLEVEL); set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_DOCK"); image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG); gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (box), focus_label (window), FALSE, FALSE, 0); button = gtk_button_new_with_label ("Close"); gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0); g_signal_connect_swapped (G_OBJECT (button), "clicked", G_CALLBACK (gtk_widget_destroy), window); gtk_container_add (GTK_CONTAINER (window), box); #define DOCK_SIZE 48 switch (type) { case DOCK_LEFT: gtk_widget_set_size_request (window, DOCK_SIZE, 400); gtk_window_move (GTK_WINDOW (window), 0, 000); set_gtk_window_struts (window, DOCK_SIZE, 0, 0, 0); gtk_window_set_title (GTK_WINDOW (window), "LeftDock"); break; case DOCK_RIGHT: gtk_widget_set_size_request (window, DOCK_SIZE, 400); gtk_window_move (GTK_WINDOW (window), gdk_screen_width () - DOCK_SIZE, 200); set_gtk_window_struts (window, 0, DOCK_SIZE, 0, 0); gtk_window_set_title (GTK_WINDOW (window), "RightDock"); break; case DOCK_TOP: gtk_widget_set_size_request (window, 600, DOCK_SIZE); gtk_window_move (GTK_WINDOW (window), 76, 0); set_gtk_window_struts (window, 0, 0, DOCK_SIZE, 0); gtk_window_set_title (GTK_WINDOW (window), "TopDock"); break; case DOCK_BOTTOM: gtk_widget_set_size_request (window, 600, DOCK_SIZE); gtk_window_move (GTK_WINDOW (window), 200, gdk_screen_height () - DOCK_SIZE); set_gtk_window_struts (window, 0, 0, 0, DOCK_SIZE); gtk_window_set_title (GTK_WINDOW (window), "BottomDock"); break; case DOCK_ALL: break; } gtk_widget_show_all (window); } static void dock_cb (GtkAction *action, gpointer callback_data) { guint callback_action; const gchar *name; name = gtk_action_get_name (action); if (!g_strcmp0 (name, "Top dock")) callback_action = DOCK_TOP; else if (!g_strcmp0 (name, "Bottom dock")) callback_action = DOCK_BOTTOM; else if (!g_strcmp0 (name, "Left dock")) callback_action = DOCK_LEFT; else if (!g_strcmp0 (name, "Right dock")) callback_action = DOCK_RIGHT; else if (!g_strcmp0 (name, "All docks")) callback_action = DOCK_ALL; else return; if (callback_action == DOCK_ALL) { make_dock (DOCK_TOP); make_dock (DOCK_BOTTOM); make_dock (DOCK_LEFT); make_dock (DOCK_RIGHT); } else { make_dock (callback_action); } } static void desktop_cb (GtkAction *action, gpointer callback_data) { GtkWidget *window; GtkWidget *label; GdkRGBA desktop_color; window = gtk_window_new (GTK_WINDOW_TOPLEVEL); set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_DESKTOP"); gtk_window_set_title (GTK_WINDOW (window), "Desktop"); gtk_widget_set_size_request (window, gdk_screen_width (), gdk_screen_height ()); gtk_window_move (GTK_WINDOW (window), 0, 0); desktop_color.red = 0.32; desktop_color.green = 0.46; desktop_color.blue = 0.65; desktop_color.alpha = 1.0; gtk_widget_override_background_color (window, 0, &desktop_color); label = focus_label (window); gtk_container_add (GTK_CONTAINER (window), label); gtk_widget_show_all (window); } static void sleep_cb (GtkAction *action, gpointer data) { sleep (1000); } static void toggle_aspect_ratio (GtkAction *action, gpointer data) { GtkWidget *window; GdkGeometry geom; GtkWidget *widget = GTK_WIDGET (data); if (aspect_on) { geom.min_aspect = 0; geom.max_aspect = 65535; } else { geom.min_aspect = 1.777778; geom.max_aspect = 1.777778; } aspect_on = !aspect_on; window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW); if (window) gtk_window_set_geometry_hints (GTK_WINDOW (window), widget, &geom, GDK_HINT_ASPECT); } static void toggle_decorated_cb (GtkWidget *button, gpointer data) { GtkWidget *window; window = gtk_widget_get_ancestor (data, GTK_TYPE_WINDOW); if (window) gtk_window_set_decorated (GTK_WINDOW (window), !gtk_window_get_decorated (GTK_WINDOW (window))); } static void clicked_toolbar_cb (GtkWidget *button, gpointer data) { GtkWidget *dialog; dialog = gtk_message_dialog_new (GTK_WINDOW (data), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "Clicking the toolbar buttons doesn't do anything"); /* Close dialog on user response */ g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (gtk_widget_destroy), NULL); gtk_widget_show (dialog); } static void update_statusbar (GtkTextBuffer *buffer, GtkStatusbar *statusbar) { gchar *msg; gint row, col; gint count; GtkTextIter iter; gtk_statusbar_pop (statusbar, 0); /* clear any previous message, underflow is allowed */ count = gtk_text_buffer_get_char_count (buffer); gtk_text_buffer_get_iter_at_mark (buffer, &iter, gtk_text_buffer_get_insert (buffer)); row = gtk_text_iter_get_line (&iter); col = gtk_text_iter_get_line_offset (&iter); msg = g_strdup_printf ("Cursor at row %d column %d - %d chars in document", row, col, count); gtk_statusbar_push (statusbar, 0, msg); g_free (msg); } static void mark_set_callback (GtkTextBuffer *buffer, const GtkTextIter *new_location, GtkTextMark *mark, gpointer data) { update_statusbar (buffer, GTK_STATUSBAR (data)); } static int window_count = 0; static void destroy_cb (GtkWidget *w, gpointer data) { --window_count; if (window_count == 0) gtk_main_quit (); } static const gchar *menu_item_string = "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n"; static const GtkActionEntry menu_items[] = { { "Windows", NULL, "_Windows", NULL, NULL, NULL }, { "Dialog", NULL, "_Dialog", "d", NULL, G_CALLBACK (dialog_cb) }, { "Modal dialog", NULL, "_Modal dialog", NULL, NULL, G_CALLBACK (modal_dialog_cb) }, { "Parentless dialog", NULL, "_Parentless dialog", NULL, NULL, G_CALLBACK (no_parent_dialog_cb) }, { "Utility", NULL, "_Utility", "u", NULL, G_CALLBACK (utility_cb) }, { "Splashscreen", NULL, "_Splashscreen", "s", NULL, G_CALLBACK (splashscreen_cb) }, { "Top dock", NULL, "_Top dock", NULL, NULL, G_CALLBACK (dock_cb) }, { "Bottom dock", NULL, "_Bottom dock", NULL, NULL, G_CALLBACK (dock_cb) }, { "Left dock", NULL, "_Left dock", NULL, NULL, G_CALLBACK (dock_cb) }, { "Right dock", NULL, "_Right dock", NULL, NULL, G_CALLBACK (dock_cb) }, { "All docks", NULL, "_All docks", NULL, NULL, G_CALLBACK (dock_cb) }, { "Desktop", NULL, "Des_ktop", NULL, NULL, G_CALLBACK (desktop_cb) }, { "Menu", NULL, "Me_nu", NULL, NULL, G_CALLBACK (menu_cb) }, { "Toolbar", NULL, "Tool_bar", NULL, NULL, G_CALLBACK (toolbar_cb) }, { "Override Redirect", NULL, "Override Redirect", NULL, NULL, G_CALLBACK (override_redirect_cb) }, { "Border Only", NULL, "Border Only", NULL, NULL, G_CALLBACK (border_only_cb) } }; static const GtkActionEntry tool_items[] = { { "New", GTK_STOCK_NEW, NULL, NULL, "Open another one of these windows", G_CALLBACK (do_appwindow) }, { "Lock", GTK_STOCK_OPEN, NULL, NULL, "This is a demo button that" " locks up the demo", G_CALLBACK (sleep_cb) }, { "Decorations", GTK_STOCK_OPEN, NULL, NULL, "This is a demo button that " "toggles window decorations", G_CALLBACK (toggle_decorated_cb) }, { "Quit", GTK_STOCK_QUIT, NULL, NULL, "This is a demo button with " " a 'quit' icon", G_CALLBACK (clicked_toolbar_cb) }, { "Ratio", GTK_STOCK_OPEN, NULL, NULL, "This is a demo button that locks the aspect ratio " "using a hint", G_CALLBACK (toggle_aspect_ratio) } }; static GtkWidget * do_appwindow (void) { GtkWidget *window; GtkWidget *grid; GtkWidget *statusbar; GtkWidget *contents; GtkWidget *sw; GtkTextBuffer *buffer; GtkActionGroup *action_group; GtkUIManager *ui_manager; /* Create the toplevel window */ ++window_count; aspect_on = FALSE; window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (window), "Application Window"); g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy_cb), NULL); grid = gtk_grid_new (); gtk_widget_set_vexpand (grid, TRUE); gtk_widget_set_hexpand (grid, TRUE); gtk_container_add (GTK_CONTAINER (window), grid); /* Create the menubar */ contents = gtk_text_view_new (); action_group = gtk_action_group_new ("mainmenu"); gtk_action_group_add_actions (action_group, menu_items, G_N_ELEMENTS (menu_items), window); gtk_action_group_add_actions (action_group, tool_items, G_N_ELEMENTS (tool_items), window); ui_manager = gtk_ui_manager_new (); gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); /* create menu items */ gtk_ui_manager_add_ui_from_string (ui_manager, menu_item_string, -1, NULL); gtk_grid_attach (GTK_GRID (grid), gtk_ui_manager_get_widget (ui_manager, "/ui/menubar"), 0, 0, 1, 1); gtk_widget_set_hexpand (gtk_ui_manager_get_widget (ui_manager, "/ui/menubar"), TRUE); /* Create document */ sw = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN); gtk_grid_attach (GTK_GRID (grid), sw, 0, 2, 1, 1); gtk_widget_set_hexpand (sw, TRUE); gtk_widget_set_vexpand (sw, TRUE); gtk_window_set_default_size (GTK_WINDOW (window), 200, 200); gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (contents), PANGO_WRAP_WORD); gtk_container_add (GTK_CONTAINER (sw), contents); /* Create the toolbar */ gtk_grid_attach (GTK_GRID (grid), gtk_ui_manager_get_widget (ui_manager, "/ui/toolbar"), 0, 1, 1, 1); gtk_widget_set_hexpand (gtk_ui_manager_get_widget (ui_manager, "/ui/toolbar"), TRUE); /* Create statusbar */ statusbar = gtk_statusbar_new (); gtk_grid_attach (GTK_GRID (grid), statusbar, 0, 3, 1, 1); gtk_widget_set_hexpand (statusbar, TRUE); /* Show text widget info in the statusbar */ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (contents)); gtk_text_buffer_set_text (buffer, "This demo demonstrates various kinds of windows that " "window managers and window manager themes should handle. " "Be sure to tear off the menu and toolbar, those are also " "a special kind of window.", -1); g_signal_connect_object (buffer, "changed", G_CALLBACK (update_statusbar), statusbar, 0); g_signal_connect_object (buffer, "mark_set", /* cursor moved */ G_CALLBACK (mark_set_callback), statusbar, 0); update_statusbar (buffer, GTK_STATUSBAR (statusbar)); gtk_widget_show_all (window); g_object_unref (ui_manager); return window; } muffin-2.8.4/src/tools/muffin-grayscale.c0000664000175000017500000000474512623653707017311 0ustar fabiofabio/* Hack for grayscaling an image */ /* * Copyright (C) 2002 Red Hat 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #include #include #include #include #define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11) static GdkPixbuf* grayscale_pixbuf (GdkPixbuf *pixbuf) { GdkPixbuf *gray; guchar *pixels; int rowstride; int pixstride; int row; int n_rows; int width; gray = gdk_pixbuf_copy (pixbuf); rowstride = gdk_pixbuf_get_rowstride (gray); pixstride = gdk_pixbuf_get_has_alpha (gray) ? 4 : 3; pixels = gdk_pixbuf_get_pixels (gray); n_rows = gdk_pixbuf_get_height (gray); width = gdk_pixbuf_get_width (gray); row = 0; while (row < n_rows) { guchar *p = pixels + row * rowstride; guchar *end = p + (pixstride * width); while (p != end) { double v = INTENSITY (p[0], p[1], p[2]); p[0] = (guchar) v; p[1] = (guchar) v; p[2] = (guchar) v; p += pixstride; } ++row; } return gray; } int main (int argc, char **argv) { GdkPixbuf *pixbuf; GdkPixbuf *gray; GError *err; if (argc != 2) { g_printerr ("specify a single image on the command line\n"); return 1; } g_type_init (); err = NULL; pixbuf = gdk_pixbuf_new_from_file (argv[1], &err); if (err != NULL) { g_printerr ("failed to load image: %s\n", err->message); g_error_free (err); return 1; } gray = grayscale_pixbuf (pixbuf); err = NULL; gdk_pixbuf_save (gray, "grayscale.png", "png", &err, NULL); if (err != NULL) { g_printerr ("failed to save image: %s\n", err->message); g_error_free (err); return 1; } g_print ("wrote grayscale.png\n"); return 0; } muffin-2.8.4/src/tools/muffin-window-demo.png0000664000175000017500000000657512623653707020135 0ustar fabiofabioPNG  IHDR00WgAMA a 4IDATxk]uk>{}8$cLGMDE!iCP[h$VUhp*5 R5UDZUTGEj[JH&1I0C>9{Z6v?$|cs>3{Ykךz{^ojo8ij}-W  g/qk!߽ke~ޟTUĝwo{ @‰:\kNyDzzʕkϘ}U[XDCn/nhjDdXYZ3wN];SNTso?tff>|"p %+VU/ ps+Y~RW^sgxv'_#q\R~RWNgl\N=}jS7t3yG;=pB5xzz+cjKྵ&}f}{&Ba1ֹ7?Q "@#t_ڼ񁇶^3/'ǻo9!}3jw:`ӯ~KUrԊs3u> chPzHv!mii?~cW\bɿ,B8%EĈ)q֙yGĎ[=ڹ'K,p%n'ί\d=sC(D"[nmx+ [;*>.?olI" 30539Ô +Gzlg='ҩno ˙鑺 "EoW_[{ҵ ;J>W[rnB0HuBs"LU'*3XXHG|"W}.J04o/Mvu蔁,P (ʀ(11"uD*%sCH2} W}<?~љp(o{眱~fXNK'}P "Q!:Xtz]f)Bc"l[?xٟ7\v􁡤_/'''֌O,aٲU\UlxGB9h%-! 8NI_:FP(DS _~o{}\f,rݭ7}#;}s޼l1ooell)U5@͓<~\p7Bo*XJ͎ ;^"@ DU'/x\J|{޾GvgnXsDkqF;⌆3 F=8&FaF. BvCMIIIIq1"ڴywv>H|',޲/]8ieC֊ ejpBek 4888c0Aܡ0>n0S:3ī~c9olIgsWP{LL('Y$iՀꂻbfl;EuADB cQ&a? (KNZu:,#?> 1eR#[3:13[k8N2P<9Y!N!Q1N:HNP^ 5åăwmV @&9T78*XӀ) [ ?!t>9Vs nRS7rf4rG0?"&LQ`UP\ eC \@ E 7P4p挚"j7 L Ffų+i\QU"jE}QLd0?[B#تJIRVrHPYi'cʦ9 pU@JFc&V **ިWGE`8"рNYd@qI0w6M|hv&D f|¨$wv<@ph8)_SRS$42UHJUh^ɰ X#&c6jN"1;&b)nwwuQc~"!$D*䔱`ǛDFh]1&%bl U%PUDi^y07=wKudˌ!TYN]g̴ V3uRFÈcݬ*ٌlNNJ:S {l5z-UWD`玧仺[0af) b+u4bNXNEEbjJ hM9rXg\{sw+e89_;~qݣAg FV'יQh2A&*:26UhVhpJv,GԔيwC& 9@-sW^u)* 4E[co*k0Aq/m`1QDo>p;`+@=70lNJJ$M ҔI&#)f̌|$^hy@sҢ NlȻVXhyV+$U\@ hv&f"xiyq| < #include #include #include #include #include #define _(x) dgettext (GETTEXT_PACKAGE, x) #define N_(x) x static Display *display; static void send_reload_theme (void) { XEvent xev; xev.xclient.type = ClientMessage; xev.xclient.serial = 0; xev.xclient.send_event = True; xev.xclient.display = display; xev.xclient.window = gdk_x11_get_default_root_xwindow (); xev.xclient.message_type = XInternAtom (display, "_MUFFIN_RELOAD_THEME_MESSAGE", False); xev.xclient.format = 32; xev.xclient.data.l[0] = 0; xev.xclient.data.l[1] = 0; xev.xclient.data.l[2] = 0; XSendEvent (display, gdk_x11_get_default_root_xwindow (), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); XFlush (display); XSync (display, False); } static void send_set_keybindings (gboolean enabled) { XEvent xev; xev.xclient.type = ClientMessage; xev.xclient.serial = 0; xev.xclient.send_event = True; xev.xclient.display = display; xev.xclient.window = gdk_x11_get_default_root_xwindow (); xev.xclient.message_type = XInternAtom (display, "_MUFFIN_SET_KEYBINDINGS_MESSAGE", False); xev.xclient.format = 32; xev.xclient.data.l[0] = enabled; xev.xclient.data.l[1] = 0; xev.xclient.data.l[2] = 0; XSendEvent (display, gdk_x11_get_default_root_xwindow (), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); XFlush (display); XSync (display, False); } #ifdef WITH_VERBOSE_MODE static void send_toggle_verbose (void) { XEvent xev; xev.xclient.type = ClientMessage; xev.xclient.serial = 0; xev.xclient.send_event = True; xev.xclient.display = display; xev.xclient.window = gdk_x11_get_default_root_xwindow (); xev.xclient.message_type = XInternAtom (display, "_MUFFIN_TOGGLE_VERBOSE", False); xev.xclient.format = 32; xev.xclient.data.l[0] = 0; xev.xclient.data.l[1] = 0; xev.xclient.data.l[2] = 0; XSendEvent (display, gdk_x11_get_default_root_xwindow (), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); XFlush (display); XSync (display, False); } #endif static void usage (void) { g_printerr (_("Usage: %s\n"), "muffin-message (reload-theme|enable-keybindings|disable-keybindings|toggle-verbose)"); exit (1); } int main (int argc, char **argv) { bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); gtk_init (&argc, &argv); if (argc < 2) usage (); display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); if (strcmp (argv[1], "reload-theme") == 0) send_reload_theme (); else if (strcmp (argv[1], "enable-keybindings") == 0) send_set_keybindings (TRUE); else if (strcmp (argv[1], "disable-keybindings") == 0) send_set_keybindings (FALSE); else if (strcmp (argv[1], "toggle-verbose") == 0) { #ifndef WITH_VERBOSE_MODE g_printerr (_("Muffin was compiled without support for verbose mode\n")); return 1; #else send_toggle_verbose (); #endif } else usage (); return 0; } muffin-2.8.4/src/tools/Makefile.am0000664000175000017500000000152512623653707015736 0ustar fabiofabio@INTLTOOL_DESKTOP_RULE@ icondir=$(pkgdatadir)/icons icon_DATA=muffin-window-demo.png AM_CPPFLAGS=@MUFFIN_WINDOW_DEMO_CFLAGS@ @MUFFIN_MESSAGE_CFLAGS@ \ -I$(top_srcdir)/src \ -DMUFFIN_ICON_DIR=\"$(pkgdatadir)/icons\" \ -DMUFFIN_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" muffin_message_SOURCES= \ muffin-message.c muffin_window_demo_SOURCES= \ muffin-window-demo.c muffin_mag_SOURCES= \ muffin-mag.c muffin_grayscale_SOURCES= \ muffin-grayscale.c bin_PROGRAMS=muffin-message muffin-window-demo ## cheesy hacks I use, don't really have any business existing. ;-) noinst_PROGRAMS=muffin-mag muffin-grayscale muffin_message_LDADD= @MUFFIN_MESSAGE_LIBS@ muffin_window_demo_LDADD= @MUFFIN_WINDOW_DEMO_LIBS@ muffin_mag_LDADD= @MUFFIN_WINDOW_DEMO_LIBS@ muffin_grayscale_LDADD = @MUFFIN_WINDOW_DEMO_LIBS@ EXTRA_DIST=$(icon_DATA) muffin-2.8.4/src/org.cinnamon.muffin.gschema.xml.in0000664000175000017500000004725312623653707021162 0ustar fabiofabio true <_summary>Attach modal dialogs <_description> When true, instead of having independent titlebars, modal dialogs appear attached to the titlebar of the parent window and are moved together with the parent window. false <_summary>Live Hidden Windows <_description> Determines whether hidden windows (i.e., minimized windows and windows on other workspaces than the current one) should be kept alive. true <_summary>Enable edge tiling and snapping <_description> If enabled, allows you to drag windows to the screen edges to tile or snap them in place. false <_summary>Workspaces are managed dynamically <_description> Determines whether workspaces are managed dynamically or whether there's a static number of workspaces (determined by the num-workspaces key in org.cinnamon.desktop.wm.preferences). false <_summary>Fullscreen windows are unredirected (i.e. they bypass compositing) <_description> Determines whether fullscreen windows bypass compositing. False is better for vsync/screen-tearing, True gives games and apps i false <_summary>Allow cycling through workspaces <_description> Allows cycling through workspaces, going to the workspace at the other end if you are at the left-most or right-most one. false <_summary>Workspaces only on primary <_description> Determines whether workspace switching should happen for windows on all monitors or only for windows on the primary monitor. 10 <_summary>Draggable border width <_description> The amount of total draggable borders. If the theme's visible borders are not enough, invisible borders will be added to meet this value. 25 <_summary>Window tile HUD threshold <_description> The distance from the edge of the screen you must be within before the tile/snap HUD appears 24 <_summary>Window resize tension threshold <_description> The distance you have to move a resize grip before it's actually registered as a resize 'Control' <_summary>Modifier for toggling between tile and snap mode <_description> When dragging a window, holding this key will engage snap mode. false <_summary>Enable legacy drag snapping <_description> Enables old-style snapping by holding the shift key while dragging a window ":minimize,maximize,close" Arrangement of buttons on the titlebar This key overrides the key in org.cinnamon.desktop.wm.preferences when running Cinnamon. false <_summary>Inverts the direction the left and right arrows take you when you switch workspaces during a window drag <_description> Changes left-right arrow keys to window-centric directions rather than workspace-centric false <_summary>Sets maximize as the tile action for the top edge of the screen <_description> Makes tiling to the top maximize the window 'center' <_summary>Window placement mode <_description>The window placement mode indicates how new windows are positioned. "automatic" means the system chooses a location automatically based on the space available on the desktop, or by a simple cascade if there is no space; "pointer" means that new windows are placed according to the mouse pointer position; "manual" means that the user must manually place the new window with the mouse or keyboard; "center" means that the system places new windows in the center of the desktop. [] [] [] [] [] [] [] [] [] [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm [] <_summary>deprecated - moved to org.cinnamon.desktop.keybindings.wm muffin-2.8.4/src/meta/0000775000175000017500000000000012623653707013465 5ustar fabiofabiomuffin-2.8.4/src/meta/keybindings.h0000664000175000017500000000302112623653707016140 0ustar fabiofabio/* * Copyright (C) 2009 Intel Corporation. * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_KEYBINDINGS_H #define META_KEYBINDINGS_H #include #include #define META_TYPE_KEY_BINDING (meta_key_binding_get_type ()) const char *meta_key_binding_get_name (MetaKeyBinding *binding); MetaVirtualModifier meta_key_binding_get_modifiers (MetaKeyBinding *binding); guint meta_key_binding_get_mask (MetaKeyBinding *binding); gboolean meta_keybindings_set_custom_handler (const gchar *name, MetaKeyHandlerFunc handler, gpointer user_data, GDestroyNotify free_data); void meta_screen_ungrab_all_keys (MetaScreen *screen, guint32 timestamp); gboolean meta_screen_grab_all_keys (MetaScreen *screen, guint32 timestamp); #endif muffin-2.8.4/src/meta/types.h0000664000175000017500000000244312623653707015005 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* * Copyright (C) 2008 Iain Holmes * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_TYPES_H #define META_TYPES_H /** * MetaCompositor: (skip) * */ typedef struct _MetaCompositor MetaCompositor; typedef struct _MetaDisplay MetaDisplay; typedef struct _MetaFrame MetaFrame; typedef struct _MetaScreen MetaScreen; typedef struct _MetaWindow MetaWindow; typedef struct _MetaWorkspace MetaWorkspace; /** * MetaGroup: (skip) * */ typedef struct _MetaGroup MetaGroup; typedef struct _MetaKeyBinding MetaKeyBinding; #endif muffin-2.8.4/src/meta/screen.h0000664000175000017500000001076612623653707015127 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* * Copyright (C) 2008 Iain Holmes * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_SCREEN_H #define META_SCREEN_H #include #include #include #include #define META_TYPE_SCREEN (meta_screen_get_type ()) #define META_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SCREEN, MetaScreen)) #define META_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SCREEN, MetaScreenClass)) #define META_IS_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SCREEN)) #define META_IS_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SCREEN)) #define META_SCREEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SCREEN, MetaScreenClass)) typedef struct _MetaScreenClass MetaScreenClass; GType meta_screen_get_type (void); int meta_screen_get_screen_number (MetaScreen *screen); MetaDisplay *meta_screen_get_display (MetaScreen *screen); Window meta_screen_get_xroot (MetaScreen *screen); void meta_screen_get_size (MetaScreen *screen, int *width, int *height); gpointer meta_screen_get_compositor_data (MetaScreen *screen); void meta_screen_set_compositor_data (MetaScreen *screen, gpointer info); MetaScreen *meta_screen_for_x_screen (Screen *xscreen); void meta_screen_set_cm_selection (MetaScreen *screen); void meta_screen_unset_cm_selection (MetaScreen *screen); GSList *meta_screen_get_startup_sequences (MetaScreen *screen); GList *meta_screen_get_workspaces (MetaScreen *screen); int meta_screen_get_n_workspaces (MetaScreen *screen); MetaWorkspace* meta_screen_get_workspace_by_index (MetaScreen *screen, int index); void meta_screen_remove_workspace (MetaScreen *screen, MetaWorkspace *workspace, guint32 timestamp); MetaWorkspace *meta_screen_append_new_workspace (MetaScreen *screen, gboolean activate, guint32 timestamp); int meta_screen_get_active_workspace_index (MetaScreen *screen); MetaWorkspace * meta_screen_get_active_workspace (MetaScreen *screen); void meta_screen_show_desktop (MetaScreen *screen, guint32 timestamp); void meta_screen_toggle_desktop (MetaScreen *screen, guint32 timestamp); void meta_screen_unshow_desktop (MetaScreen *screen); int meta_screen_get_n_monitors (MetaScreen *screen); int meta_screen_get_primary_monitor (MetaScreen *screen); int meta_screen_get_current_monitor (MetaScreen *screen); void meta_screen_get_monitor_geometry (MetaScreen *screen, int monitor, MetaRectangle *geometry); int meta_screen_get_monitor_index_for_rect (MetaScreen *screen, MetaRectangle *rect); MetaWindow* meta_screen_get_mouse_window (MetaScreen *screen, MetaWindow *not_this_one); typedef enum { META_SCREEN_TOPLEFT, META_SCREEN_TOPRIGHT, META_SCREEN_BOTTOMLEFT, META_SCREEN_BOTTOMRIGHT } MetaScreenCorner; void meta_screen_override_workspace_layout (MetaScreen *screen, MetaScreenCorner starting_corner, gboolean vertical_layout, int n_rows, int n_columns); #endif muffin-2.8.4/src/meta/display.h0000664000175000017500000002163312623653707015310 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* * Copyright (C) 2008 Iain Holmes * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_DISPLAY_H #define META_DISPLAY_H #include #include #include #include #include typedef enum { META_TAB_LIST_NORMAL, META_TAB_LIST_DOCKS, META_TAB_LIST_GROUP, META_TAB_LIST_NORMAL_ALL } MetaTabList; typedef enum { META_TAB_SHOW_ICON, /* Alt-Tab mode */ META_TAB_SHOW_INSTANTLY /* Alt-Esc mode */ } MetaTabShowType; typedef struct _MetaDisplayClass MetaDisplayClass; #define META_TYPE_DISPLAY (meta_display_get_type ()) #define META_DISPLAY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), META_TYPE_DISPLAY, MetaDisplay)) #define META_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DISPLAY, MetaDisplayClass)) #define META_IS_DISPLAY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), META_TYPE_DISPLAY)) #define META_IS_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DISPLAY)) #define META_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DISPLAY, MetaDisplayClass)) GType meta_display_get_type (void) G_GNUC_CONST; #define meta_XFree(p) do { if ((p)) XFree ((p)); } while (0) typedef enum { META_ATOM_FIRST = 0, #define item(x) META_ATOM_##x, #include "atomnames.h" #undef item }MetaAtom; typedef enum { META_LIST_DEFAULT = 0, /* normal windows */ META_LIST_INCLUDE_OVERRIDE_REDIRECT = 1 << 0, /* normal and O-R */ } MetaListWindowsFlags; void meta_display_get_compositor_version (MetaDisplay *display, int *major, int *minor); Display *meta_display_get_xdisplay (MetaDisplay *display); MetaCompositor *meta_display_get_compositor (MetaDisplay *display); GSList *meta_display_get_screens (MetaDisplay *display); gboolean meta_display_has_shape (MetaDisplay *display); MetaScreen *meta_display_screen_for_root (MetaDisplay *display, Window xroot); MetaWindow *meta_display_get_focus_window (MetaDisplay *display); GSList* meta_display_list_windows (MetaDisplay *display, MetaListWindowsFlags flags); gboolean meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display, Window xwindow); int meta_display_get_damage_event_base (MetaDisplay *display); int meta_display_get_shape_event_base (MetaDisplay *display); Atom meta_display_get_atom (MetaDisplay *display, MetaAtom meta_atom); gboolean meta_display_xserver_time_is_before (MetaDisplay *display, guint32 time1, guint32 time2); guint32 meta_display_get_last_user_time (MetaDisplay *display); guint32 meta_display_get_current_time (MetaDisplay *display); guint32 meta_display_get_current_time_roundtrip (MetaDisplay *display); unsigned int meta_display_get_ignored_modifier_mask (MetaDisplay *display); GList* meta_display_get_tab_list (MetaDisplay *display, MetaTabList type, MetaScreen *screen, MetaWorkspace *workspace); MetaWindow* meta_display_get_tab_next (MetaDisplay *display, MetaTabList type, MetaScreen *screen, MetaWorkspace *workspace, MetaWindow *window, gboolean backward); MetaWindow* meta_display_get_tab_current (MetaDisplay *display, MetaTabList type, MetaScreen *screen, MetaWorkspace *workspace); gboolean meta_display_begin_grab_op (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, MetaGrabOp op, gboolean pointer_already_grabbed, gboolean frame_action, int button, gulong modmask, guint32 timestamp, int root_x, int root_y); void meta_display_end_grab_op (MetaDisplay *display, guint32 timestamp); MetaGrabOp meta_display_get_grab_op (MetaDisplay *display); gboolean meta_display_add_keybinding (MetaDisplay *display, const char *name, const char *schema, MetaKeyBindingFlags flags, MetaKeyHandlerFunc handler, gpointer user_data, GDestroyNotify free_data); gboolean meta_display_remove_keybinding (MetaDisplay *display, const char *name); void meta_display_rebuild_keybindings (MetaDisplay *display); gboolean meta_display_add_custom_keybinding (MetaDisplay *display, const char *name, const char **bindings, MetaKeyHandlerFunc callback, gpointer user_data, GDestroyNotify free_data); gboolean meta_display_remove_custom_keybinding (MetaDisplay *display, const char *name); MetaKeyBindingAction meta_display_get_keybinding_action (MetaDisplay *display, unsigned int keycode, unsigned long mask); /* meta_display_set_input_focus_window is like XSetInputFocus, except * that (a) it can't detect timestamps later than the current time, * since Muffin isn't part of the XServer, and thus gives erroneous * behavior in this circumstance (so don't do it), (b) it uses * display->last_focus_time since we don't have access to the true * Xserver one, (c) it makes use of display->user_time since checking * whether a window should be allowed to be focused should depend * on user_time events (see bug 167358, comment 15 in particular) */ void meta_display_set_input_focus_window (MetaDisplay *display, MetaWindow *window, gboolean focus_frame, guint32 timestamp); /* meta_display_focus_the_no_focus_window is called when the * designated no_focus_window should be focused, but is otherwise the * same as meta_display_set_input_focus_window */ void meta_display_focus_the_no_focus_window (MetaDisplay *display, MetaScreen *screen, guint32 timestamp); GSList *meta_display_sort_windows_by_stacking (MetaDisplay *display, GSList *windows); Window meta_display_get_leader_window (MetaDisplay *display); void meta_display_add_ignored_crossing_serial (MetaDisplay *display, unsigned long serial); void meta_display_unmanage_screen (MetaDisplay *display, MetaScreen *screen, guint32 timestamp); void meta_display_keybinding_action_invoke_by_code (MetaDisplay *display, unsigned int keycode, unsigned long mask); #endif muffin-2.8.4/src/meta/compositor-muffin.h0000664000175000017500000000410712623653707017320 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* * Copyright (C) 2008 Matthew Allum * Copyright (C) 2007 Iain Holmes * Based on xcompmgr - (c) 2003 Keith Packard * xfwm4 - (c) 2005-2007 Olivier Fourdan * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef MUFFIN_H_ #define MUFFIN_H_ #include #include #include #include #include #include /* Public compositor API */ ClutterActor *meta_get_stage_for_screen (MetaScreen *screen); ClutterActor *meta_get_overlay_group_for_screen (MetaScreen *screen); Window meta_get_overlay_window (MetaScreen *screen); GList *meta_get_window_actors (MetaScreen *screen); ClutterActor *meta_get_window_group_for_screen (MetaScreen *screen); ClutterActor *meta_get_bottom_window_group_for_screen (MetaScreen *screen); ClutterActor *meta_get_top_window_group_for_screen (MetaScreen *screen); void meta_disable_unredirect_for_screen (MetaScreen *screen); void meta_enable_unredirect_for_screen (MetaScreen *screen); ClutterActor *meta_get_background_actor_for_screen (MetaScreen *screen); void meta_set_stage_input_region (MetaScreen *screen, XserverRegion region); void meta_empty_stage_input_region (MetaScreen *screen); #endif muffin-2.8.4/src/meta/meta-plugin.h0000664000175000017500000003105612623653707016065 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* * Copyright (c) 2008 Intel Corp. * * Author: Tomas Frydrych * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_PLUGIN_H_ #define META_PLUGIN_H_ #include #include #include #include #include #include #define META_TYPE_PLUGIN (meta_plugin_get_type ()) #define META_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_PLUGIN, MetaPlugin)) #define META_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_PLUGIN, MetaPluginClass)) #define META_IS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_PLUGIN)) #define META_IS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_PLUGIN)) #define META_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_PLUGIN, MetaPluginClass)) /** * MetaPlugin: (skip) * */ typedef struct _MetaPlugin MetaPlugin; /** * MetaPluginClass: (skip) * */ typedef struct _MetaPluginClass MetaPluginClass; typedef struct _MetaPluginVersion MetaPluginVersion; typedef struct _MetaPluginInfo MetaPluginInfo; typedef struct _MetaPluginPrivate MetaPluginPrivate; struct _MetaPlugin { GObject parent; MetaPluginPrivate *priv; }; struct _MetaPluginClass { GObjectClass parent_class; void (*start) (MetaPlugin *plugin); void (*minimize) (MetaPlugin *plugin, MetaWindowActor *actor); void (*maximize) (MetaPlugin *plugin, MetaWindowActor *actor, gint x, gint y, gint width, gint height); void (*unmaximize) (MetaPlugin *plugin, MetaWindowActor *actor, gint x, gint y, gint width, gint height); void (*tile) (MetaPlugin *plugin, MetaWindowActor *actor, gint x, gint y, gint width, gint height); void (*map) (MetaPlugin *plugin, MetaWindowActor *actor); void (*destroy) (MetaPlugin *plugin, MetaWindowActor *actor); void (*switch_workspace) (MetaPlugin *plugin, gint from, gint to, MetaMotionDirection direction); void (*show_tile_preview) (MetaPlugin *plugin, MetaWindow *window, MetaRectangle *tile_rect, int tile_monitor_number, guint snap_queued); void (*hide_tile_preview) (MetaPlugin *plugin); void (*show_hud_preview) (MetaPlugin *plugin, guint current_proximity_zone, MetaRectangle *work_area, guint snap_queued); void (*hide_hud_preview) (MetaPlugin *plugin); /* * Called if an effects should be killed prematurely; the plugin must * call the completed() callback as if the effect terminated naturally. */ void (*kill_window_effects) (MetaPlugin *plugin, MetaWindowActor *actor); /* General XEvent filter. This is fired *before* meta itself handles * an event. Return TRUE to block any further processing. */ gboolean (*xevent_filter) (MetaPlugin *plugin, XEvent *event); const MetaPluginInfo * (*plugin_info) (MetaPlugin *plugin); }; struct _MetaPluginInfo { const gchar *name; const gchar *version; const gchar *author; const gchar *license; const gchar *description; }; GType meta_plugin_get_type (void); gboolean meta_plugin_running (MetaPlugin *plugin); gboolean meta_plugin_debug_mode (MetaPlugin *plugin); const MetaPluginInfo * meta_plugin_get_info (MetaPlugin *plugin); struct _MetaPluginVersion { /* * Version information; the first three numbers match the Meta version * with which the plugin was compiled (see clutter-plugins/simple.c for sample * code). */ guint version_major; guint version_minor; guint version_micro; /* * Version of the plugin API; this is unrelated to the matacity version * per se. The API version is checked by the plugin manager and must match * the one used by it (see clutter-plugins/default.c for sample code). */ guint version_api; }; /* * Convenience macro to set up the plugin type. Based on GEdit. */ #define META_PLUGIN_DECLARE(ObjectName, object_name) \ G_MODULE_EXPORT MetaPluginVersion meta_plugin_version = \ { \ MUFFIN_MAJOR_VERSION, \ MUFFIN_MINOR_VERSION, \ MUFFIN_MICRO_VERSION, \ MUFFIN_PLUGIN_API_VERSION \ }; \ \ static GType g_define_type_id = 0; \ \ /* Prototypes */ \ G_MODULE_EXPORT \ GType object_name##_get_type (void); \ \ G_MODULE_EXPORT \ GType object_name##_register_type (GTypeModule *type_module); \ \ G_MODULE_EXPORT \ GType meta_plugin_register_type (GTypeModule *type_module); \ \ GType \ object_name##_get_type () \ { \ return g_define_type_id; \ } \ \ static void object_name##_init (ObjectName *self); \ static void object_name##_class_init (ObjectName##Class *klass); \ static gpointer object_name##_parent_class = NULL; \ static void object_name##_class_intern_init (gpointer klass) \ { \ object_name##_parent_class = g_type_class_peek_parent (klass); \ object_name##_class_init ((ObjectName##Class *) klass); \ } \ \ GType \ object_name##_register_type (GTypeModule *type_module) \ { \ static const GTypeInfo our_info = \ { \ sizeof (ObjectName##Class), \ NULL, /* base_init */ \ NULL, /* base_finalize */ \ (GClassInitFunc) object_name##_class_intern_init, \ NULL, \ NULL, /* class_data */ \ sizeof (ObjectName), \ 0, /* n_preallocs */ \ (GInstanceInitFunc) object_name##_init \ }; \ \ g_define_type_id = g_type_module_register_type (type_module, \ META_TYPE_PLUGIN, \ #ObjectName, \ &our_info, \ 0); \ \ \ return g_define_type_id; \ } \ \ G_MODULE_EXPORT GType \ meta_plugin_register_type (GTypeModule *type_module) \ { \ return object_name##_register_type (type_module); \ } \ void meta_plugin_switch_workspace_completed (MetaPlugin *plugin); void meta_plugin_minimize_completed (MetaPlugin *plugin, MetaWindowActor *actor); void meta_plugin_maximize_completed (MetaPlugin *plugin, MetaWindowActor *actor); void meta_plugin_unmaximize_completed (MetaPlugin *plugin, MetaWindowActor *actor); void meta_plugin_tile_completed (MetaPlugin *plugin, MetaWindowActor *actor); void meta_plugin_map_completed (MetaPlugin *plugin, MetaWindowActor *actor); void meta_plugin_destroy_completed (MetaPlugin *plugin, MetaWindowActor *actor); /** * MetaModalOptions: * @META_MODAL_POINTER_ALREADY_GRABBED: if set the pointer is already * grabbed by the plugin and should not be grabbed again. * @META_MODAL_KEYBOARD_ALREADY_GRABBED: if set the keyboard is already * grabbed by the plugin and should not be grabbed again. * * Options that can be provided when calling meta_plugin_begin_modal(). */ typedef enum { META_MODAL_POINTER_ALREADY_GRABBED = 1 << 0, META_MODAL_KEYBOARD_ALREADY_GRABBED = 1 << 1 } MetaModalOptions; gboolean meta_plugin_begin_modal (MetaPlugin *plugin, Window grab_window, Cursor cursor, MetaModalOptions options, guint32 timestamp); void meta_plugin_end_modal (MetaPlugin *plugin, guint32 timestamp); MetaScreen *meta_plugin_get_screen (MetaPlugin *plugin); void _meta_plugin_effect_started (MetaPlugin *plugin); /* Putting this here so it's in the public header */ void meta_plugin_manager_set_plugin_type (GType gtype); #endif /* META_PLUGIN_H_ */ muffin-2.8.4/src/meta/preview-widget.h0000664000175000017500000000607312623653707016606 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* Metacity theme preview widget */ /* * Copyright (C) 2002 Havoc Pennington * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #include #include #include #include #ifndef META_PREVIEW_WIDGET_H #define META_PREVIEW_WIDGET_H #define META_TYPE_PREVIEW (meta_preview_get_type ()) #define META_PREVIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_PREVIEW, MetaPreview)) #define META_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_PREVIEW, MetaPreviewClass)) #define META_IS_PREVIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_PREVIEW)) #define META_IS_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_PREVIEW)) #define META_PREVIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_PREVIEW, MetaPreviewClass)) typedef struct _MetaPreview MetaPreview; typedef struct _MetaPreviewClass MetaPreviewClass; struct _MetaPreview { GtkBin bin; MetaTheme *theme; char *title; MetaFrameType type; MetaFrameFlags flags; PangoLayout *layout; int text_height; MetaFrameBorders borders; guint borders_cached : 1; MetaButtonLayout button_layout; }; struct _MetaPreviewClass { GtkBinClass parent_class; }; GType meta_preview_get_type (void) G_GNUC_CONST; GtkWidget* meta_preview_new (void); void meta_preview_set_theme (MetaPreview *preview, MetaTheme *theme); void meta_preview_set_title (MetaPreview *preview, const char *title); void meta_preview_set_frame_type (MetaPreview *preview, MetaFrameType type); void meta_preview_set_frame_flags (MetaPreview *preview, MetaFrameFlags flags); void meta_preview_set_button_layout (MetaPreview *preview, const MetaButtonLayout *button_layout); cairo_region_t * meta_preview_get_clip_region (MetaPreview *preview, gint new_window_width, gint new_window_height); GdkPixbuf* meta_preview_get_icon (void); GdkPixbuf* meta_preview_get_mini_icon (void); #endif muffin-2.8.4/src/meta/group.h0000664000175000017500000000336412623653707015000 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* Muffin window groups */ /* * Copyright (C) 2002 Red Hat 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_GROUP_H #define META_GROUP_H #include #include #include /* note, can return NULL */ MetaGroup* meta_window_get_group (MetaWindow *window); void meta_window_compute_group (MetaWindow* window); void meta_window_shutdown_group (MetaWindow *window); void meta_window_group_leader_changed (MetaWindow *window); /* note, can return NULL */ MetaGroup* meta_display_lookup_group (MetaDisplay *display, Window group_leader); GSList* meta_group_list_windows (MetaGroup *group); void meta_group_update_layers (MetaGroup *group); const char* meta_group_get_startup_id (MetaGroup *group); int meta_group_get_size (MetaGroup *group); gboolean meta_group_property_notify (MetaGroup *group, XEvent *event); #endif muffin-2.8.4/src/meta/meta-shadow-factory.h0000664000175000017500000000660712623653707017525 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* * MetaShadowFactory: * * Create and cache shadow textures for arbitrary window shapes * * Copyright (C) 2010 Red Hat, 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef __META_SHADOW_FACTORY_H__ #define __META_SHADOW_FACTORY_H__ #include /** * MetaShadowParams: * The #MetaShadowParams structure holds information about how to draw * a particular style of shadow. * @radius: the radius (gaussian standard deviation) of the shadow * @top_fade: if >= 0, the shadow doesn't extend above the top * of the shape, and fades out over the given number of pixels * @x_offset: horizontal offset of the shadow with respect to the * shape being shadowed, in pixels * @y_offset: vertical offset of the shadow with respect to the * shape being shadowed, in pixels * @opacity: opacity of the shadow, from 0 to 255 */ typedef struct _MetaShadowParams MetaShadowParams; struct _MetaShadowParams { int radius; int top_fade; int x_offset; int y_offset; guint8 opacity; }; #define META_TYPE_SHADOW_FACTORY (meta_shadow_factory_get_type ()) #define META_SHADOW_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SHADOW_FACTORY, MetaShadowFactory)) #define META_SHADOW_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SHADOW_FACTORY, MetaShadowFactoryClass)) #define META_IS_SHADOW_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SHADOW_FACTORY)) #define META_IS_SHADOW_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SHADOW_FACTORY)) #define META_SHADOW_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SHADOW_FACTORY, MetaShadowFactoryClass)) /** * MetaShadowFactory: * #MetaShadowFactory is used to create window shadows. It caches shadows internally * so that multiple shadows created for the same shape with the same radius will * share the same MetaShadow. */ typedef struct _MetaShadowFactory MetaShadowFactory; typedef struct _MetaShadowFactoryClass MetaShadowFactoryClass; MetaShadowFactory *meta_shadow_factory_get_default (void); GType meta_shadow_factory_get_type (void); void meta_shadow_factory_set_params (MetaShadowFactory *factory, const char *class_name, gboolean focused, MetaShadowParams *params); void meta_shadow_factory_get_params (MetaShadowFactory *factory, const char *class_name, gboolean focused, MetaShadowParams *params); #endif /* __META_SHADOW_FACTORY_H__ */ muffin-2.8.4/src/meta/errors.h0000664000175000017500000000241212623653707015151 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* Muffin X error handling */ /* * Copyright (C) 2001 Havoc Pennington * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_ERRORS_H #define META_ERRORS_H #include #include #include void meta_error_trap_push (MetaDisplay *display); void meta_error_trap_pop (MetaDisplay *display); void meta_error_trap_push_with_return (MetaDisplay *display); /* returns X error code, or 0 for no error */ int meta_error_trap_pop_with_return (MetaDisplay *display); #endif muffin-2.8.4/src/meta/meta-background-actor.h0000664000175000017500000000470212623653707020012 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* * meta-background-actor.h: Actor for painting the root window background * * Copyright 2010 Red Hat, 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_BACKGROUND_ACTOR_H #define META_BACKGROUND_ACTOR_H #include #include /** * MetaBackgroundActor: * * This class handles tracking and painting the root window background. * By integrating with #MetaWindowGroup we can avoid painting parts of * the background that are obscured by other windows. */ #define META_TYPE_BACKGROUND_ACTOR (meta_background_actor_get_type ()) #define META_BACKGROUND_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKGROUND_ACTOR, MetaBackgroundActor)) #define META_BACKGROUND_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_BACKGROUND_ACTOR, MetaBackgroundActorClass)) #define META_IS_BACKGROUND_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BACKGROUND_ACTOR)) #define META_IS_BACKGROUND_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_BACKGROUND_ACTOR)) #define META_BACKGROUND_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_BACKGROUND_ACTOR, MetaBackgroundActorClass)) typedef struct _MetaBackgroundActor MetaBackgroundActor; typedef struct _MetaBackgroundActorClass MetaBackgroundActorClass; typedef struct _MetaBackgroundActorPrivate MetaBackgroundActorPrivate; struct _MetaBackgroundActorClass { ClutterActorClass parent_class; }; struct _MetaBackgroundActor { ClutterActor parent; MetaBackgroundActorPrivate *priv; }; GType meta_background_actor_get_type (void); ClutterActor *meta_background_actor_new_for_screen (MetaScreen *screen); #endif /* META_BACKGROUND_ACTOR_H */ muffin-2.8.4/src/meta/boxes.h0000664000175000017500000000733012623653707014761 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* Simple box operations */ /* * Copyright (C) 2005, 2006 Elijah Newren * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_BOXES_H #define META_BOXES_H #include #include #define META_TYPE_RECTANGLE (meta_rectangle_get_type ()) typedef struct _MetaRectangle MetaRectangle; struct _MetaRectangle { int x; int y; int width; int height; }; typedef struct _MetaStrut MetaStrut; struct _MetaStrut { MetaRectangle rect; MetaSide side; }; typedef enum { META_EDGE_WINDOW, META_EDGE_MONITOR, META_EDGE_SCREEN } MetaEdgeType; typedef struct _MetaEdge MetaEdge; struct _MetaEdge { MetaRectangle rect; /* width or height should be 1 */ MetaSide side_type; MetaEdgeType edge_type; }; GType meta_rectangle_get_type (void); MetaRectangle *meta_rectangle_copy (const MetaRectangle *rect); void meta_rectangle_free (MetaRectangle *rect); /* Function to make initializing a rect with a single line of code easy */ MetaRectangle meta_rect (int x, int y, int width, int height); /* Basic comparison functions */ int meta_rectangle_area (const MetaRectangle *rect); gboolean meta_rectangle_intersect (const MetaRectangle *src1, const MetaRectangle *src2, MetaRectangle *dest); gboolean meta_rectangle_equal (const MetaRectangle *src1, const MetaRectangle *src2); /* Find the bounding box of the union of two rectangles */ void meta_rectangle_union (const MetaRectangle *rect1, const MetaRectangle *rect2, MetaRectangle *dest); /* overlap is similar to intersect but doesn't provide location of * intersection information. */ gboolean meta_rectangle_overlap (const MetaRectangle *rect1, const MetaRectangle *rect2); /* vert_overlap means ignore the horizontal location and ask if the * vertical parts overlap. An alternate way to think of it is "Does there * exist a way to shift either rect horizontally so that the two rects * overlap?" horiz_overlap is similar. */ gboolean meta_rectangle_vert_overlap (const MetaRectangle *rect1, const MetaRectangle *rect2); gboolean meta_rectangle_horiz_overlap (const MetaRectangle *rect1, const MetaRectangle *rect2); /* could_fit_rect determines whether "outer_rect" is big enough to contain * inner_rect. contains_rect checks whether it actually contains it. */ gboolean meta_rectangle_could_fit_rect (const MetaRectangle *outer_rect, const MetaRectangle *inner_rect); gboolean meta_rectangle_contains_rect (const MetaRectangle *outer_rect, const MetaRectangle *inner_rect); #endif /* META_BOXES_H */ muffin-2.8.4/src/meta/main.h0000664000175000017500000000253712623653707014571 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* Muffin main */ /* * Copyright (C) 2001 Havoc Pennington * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_MAIN_H #define META_MAIN_H #include GOptionContext *meta_get_option_context (void); void meta_init (void); int meta_run (void); gboolean meta_get_replace_current_wm (void); /* Actually defined in util.c */ typedef enum { META_EXIT_SUCCESS, META_EXIT_ERROR } MetaExitCode; /* exit immediately */ void meta_exit (MetaExitCode code); /* g_main_loop_quit() then fall out of main() */ void meta_quit (MetaExitCode code); #endif muffin-2.8.4/src/meta/window.h0000664000175000017500000002204012623653707015143 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* * Copyright (C) 2008 Iain Holmes * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_WINDOW_H #define META_WINDOW_H #include #include #include #include #include typedef enum { META_WINDOW_NORMAL, META_WINDOW_DESKTOP, META_WINDOW_DOCK, META_WINDOW_DIALOG, META_WINDOW_MODAL_DIALOG, META_WINDOW_TOOLBAR, META_WINDOW_MENU, META_WINDOW_UTILITY, META_WINDOW_SPLASHSCREEN, /* override redirect window types: */ META_WINDOW_DROPDOWN_MENU, META_WINDOW_POPUP_MENU, META_WINDOW_TOOLTIP, META_WINDOW_NOTIFICATION, META_WINDOW_COMBO, META_WINDOW_DND, META_WINDOW_OVERRIDE_OTHER } MetaWindowType; typedef enum { META_MAXIMIZE_HORIZONTAL = 1 << 0, META_MAXIMIZE_VERTICAL = 1 << 1 } MetaMaximizeFlags; #define META_TYPE_WINDOW (meta_window_get_type ()) #define META_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_WINDOW, MetaWindow)) #define META_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_WINDOW, MetaWindowClass)) #define META_IS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_WINDOW)) #define META_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_WINDOW)) #define META_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_WINDOW, MetaWindowClass)) typedef struct _MetaWindowClass MetaWindowClass; GType meta_window_get_type (void); MetaFrame *meta_window_get_frame (MetaWindow *window); gboolean meta_window_has_focus (MetaWindow *window); gboolean meta_window_appears_focused (MetaWindow *window); gboolean meta_window_is_shaded (MetaWindow *window); gboolean meta_window_is_override_redirect (MetaWindow *window); gboolean meta_window_is_skip_taskbar (MetaWindow *window); MetaRectangle *meta_window_get_rect (MetaWindow *window); void meta_window_get_input_rect (const MetaWindow *window, MetaRectangle *rect); void meta_window_get_outer_rect (const MetaWindow *window, MetaRectangle *rect); MetaScreen *meta_window_get_screen (MetaWindow *window); MetaDisplay *meta_window_get_display (MetaWindow *window); unsigned long meta_window_get_xwindow (MetaWindow *window); MetaWindowType meta_window_get_window_type (MetaWindow *window); Atom meta_window_get_window_type_atom (MetaWindow *window); MetaWorkspace *meta_window_get_workspace (MetaWindow *window); int meta_window_get_monitor (MetaWindow *window); gboolean meta_window_is_on_all_workspaces (MetaWindow *window); gboolean meta_window_is_hidden (MetaWindow *window); void meta_window_activate (MetaWindow *window,guint32 current_time); void meta_window_activate_with_workspace (MetaWindow *window, guint32 current_time, MetaWorkspace *workspace); const char * meta_window_get_description (MetaWindow *window); const char * meta_window_get_wm_class (MetaWindow *window); const char * meta_window_get_wm_class_instance (MetaWindow *window); gboolean meta_window_showing_on_its_workspace (MetaWindow *window); const char * meta_window_get_gtk_application_id (MetaWindow *window); const char * meta_window_get_gtk_unique_bus_name (MetaWindow *window); const char * meta_window_get_gtk_application_object_path (MetaWindow *window); const char * meta_window_get_gtk_window_object_path (MetaWindow *window); const char * meta_window_get_gtk_app_menu_object_path (MetaWindow *window); const char * meta_window_get_gtk_menubar_object_path (MetaWindow *window); void meta_window_move(MetaWindow *window, gboolean user_op, int root_x_nw, int root_y_nw); void meta_window_move_frame(MetaWindow *window, gboolean user_op, int root_x_nw, int root_y_nw); void meta_window_move_resize_frame (MetaWindow *window, gboolean user_op, int root_x_nw, int root_y_nw, int w, int h); void meta_window_move_to_monitor (MetaWindow *window, int monitor); void meta_window_resize(MetaWindow *window, gboolean user_op, int w, int h); void meta_window_set_demands_attention (MetaWindow *window); void meta_window_unset_demands_attention (MetaWindow *window); const char* meta_window_get_startup_id (MetaWindow *window); void meta_window_change_workspace_by_index (MetaWindow *window, gint space_index, gboolean append, guint32 timestamp); void meta_window_change_workspace (MetaWindow *window, MetaWorkspace *workspace); void meta_window_stick (MetaWindow *window); void meta_window_unstick (MetaWindow *window); GObject *meta_window_get_compositor_private (MetaWindow *window); void meta_window_set_compositor_private (MetaWindow *window, GObject *priv); void meta_window_configure_notify (MetaWindow *window, XConfigureEvent *event); const char *meta_window_get_role (MetaWindow *window); MetaStackLayer meta_window_get_layer (MetaWindow *window); MetaWindow* meta_window_find_root_ancestor (MetaWindow *window); gboolean meta_window_is_ancestor_of_transient (MetaWindow *window, MetaWindow *transient); typedef gboolean (*MetaWindowForeachFunc) (MetaWindow *window, void *data); void meta_window_foreach_transient (MetaWindow *window, MetaWindowForeachFunc func, void *user_data); void meta_window_foreach_ancestor (MetaWindow *window, MetaWindowForeachFunc func, void *user_data); MetaMaximizeFlags meta_window_get_maximized (MetaWindow *window); gboolean meta_window_is_fullscreen (MetaWindow *window); gboolean meta_window_is_monitor_sized (MetaWindow *window); gboolean meta_window_is_on_primary_monitor (MetaWindow *window); gboolean meta_window_is_demanding_attention (MetaWindow *window); gboolean meta_window_is_urgent (MetaWindow *window); gboolean meta_window_requested_bypass_compositor (MetaWindow *window); gboolean meta_window_requested_dont_bypass_compositor (MetaWindow *window); gboolean meta_window_is_mapped (MetaWindow *window); gboolean meta_window_toplevel_is_mapped (MetaWindow *window); gboolean meta_window_get_icon_geometry (MetaWindow *window, MetaRectangle *rect); void meta_window_set_icon_geometry (MetaWindow *window, MetaRectangle *rect); void meta_window_maximize (MetaWindow *window, MetaMaximizeFlags directions); void meta_window_unmaximize (MetaWindow *window, MetaMaximizeFlags directions); void meta_window_minimize (MetaWindow *window); void meta_window_unminimize (MetaWindow *window); void meta_window_raise (MetaWindow *window); void meta_window_lower (MetaWindow *window); void meta_window_reset_opacity (MetaWindow *window); const char *meta_window_get_title (MetaWindow *window); MetaWindow *meta_window_get_transient_for (MetaWindow *window); Window meta_window_get_transient_for_as_xid (MetaWindow *window); void meta_window_delete (MetaWindow *window, guint32 timestamp); guint meta_window_get_stable_sequence (MetaWindow *window); guint32 meta_window_get_user_time (MetaWindow *window); int meta_window_get_pid (MetaWindow *window); const char *meta_window_get_client_machine (MetaWindow *window); gboolean meta_window_is_remote (MetaWindow *window); gboolean meta_window_is_modal (MetaWindow *window); gboolean meta_window_is_attached_dialog (MetaWindow *window); const char *meta_window_get_muffin_hints (MetaWindow *window); MetaFrameType meta_window_get_frame_type (MetaWindow *window); cairo_region_t *meta_window_get_frame_bounds (MetaWindow *window); MetaWindow *meta_window_get_tile_match (MetaWindow *window); gboolean meta_window_can_tile (MetaWindow *window, MetaTileMode mode); gboolean meta_window_tile (MetaWindow *window, MetaTileMode mode, gboolean snap); #endif muffin-2.8.4/src/meta/meta-shaped-texture.h0000664000175000017500000000671512623653707017535 0ustar fabiofabio/* * shaped texture * * An actor to draw a texture clipped to a list of rectangles * * Authored By Neil Roberts * * Copyright (C) 2008 Intel Corporation * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef __META_SHAPED_TEXTURE_H__ #define __META_SHAPED_TEXTURE_H__ #include #include G_BEGIN_DECLS #define META_TYPE_SHAPED_TEXTURE (meta_shaped_texture_get_type()) #define META_SHAPED_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),META_TYPE_SHAPED_TEXTURE, MetaShapedTexture)) #define META_SHAPED_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SHAPED_TEXTURE, MetaShapedTextureClass)) #define META_IS_SHAPED_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SHAPED_TEXTURE)) #define META_IS_SHAPED_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SHAPED_TEXTURE)) #define META_SHAPED_TEXTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SHAPED_TEXTURE, MetaShapedTextureClass)) typedef struct _MetaShapedTexture MetaShapedTexture; typedef struct _MetaShapedTextureClass MetaShapedTextureClass; typedef struct _MetaShapedTexturePrivate MetaShapedTexturePrivate; struct _MetaShapedTextureClass { ClutterActorClass parent_class; }; struct _MetaShapedTexture { ClutterActor parent; MetaShapedTexturePrivate *priv; }; GType meta_shaped_texture_get_type (void) G_GNUC_CONST; ClutterActor *meta_shaped_texture_new (void); void meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex, gboolean create_mipmaps); void meta_shaped_texture_update_area (MetaShapedTexture *stex, int x, int y, int width, int height); void meta_shaped_texture_set_pixmap (MetaShapedTexture *stex, Pixmap pixmap); CoglHandle meta_shaped_texture_get_texture (MetaShapedTexture *stex); void meta_shaped_texture_set_shape_region (MetaShapedTexture *stex, cairo_region_t *region); void meta_shaped_texture_set_overlay_path (MetaShapedTexture *stex, cairo_region_t *overlay_region, cairo_path_t *overlay_path); /* Assumes ownership of clip_region */ void meta_shaped_texture_set_clip_region (MetaShapedTexture *stex, cairo_region_t *clip_region); cairo_surface_t * meta_shaped_texture_get_image (MetaShapedTexture *stex, cairo_rectangle_int_t *clip); G_END_DECLS #endif /* __META_SHAPED_TEXTURE_H__ */ muffin-2.8.4/src/meta/workspace.h0000664000175000017500000000562512623653707015644 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* * Copyright (C) 2001 Havoc Pennington * Copyright (C) 2004, 2005 Elijah Newren * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_WORKSPACE_H #define META_WORKSPACE_H /** * SECTION:Workspaces * @short_description:Workspaces * * A workspace is a set of windows which all live on the same * screen. (You may also see the name "desktop" around the place, * which is the EWMH's name for the same thing.) Only one workspace * of a screen may be active at once; all windows on all other workspaces * are unmapped. */ #include #include #include #define META_TYPE_WORKSPACE (meta_workspace_get_type ()) #define META_WORKSPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_WORKSPACE, MetaWorkspace)) #define META_WORKSPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_WORKSPACE, MetaWorkspaceClass)) #define META_IS_WORKSPACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_WORKSPACE_TYPE)) #define META_IS_WORKSPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_WORKSPACE)) #define META_WORKSPACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_WORKSPACE, MetaWorkspaceClass)) typedef struct _MetaWorkspaceClass MetaWorkspaceClass; GType meta_workspace_get_type (void); int meta_workspace_index (MetaWorkspace *workspace); GList* meta_workspace_list_windows (MetaWorkspace *workspace); void meta_workspace_get_work_area_all_monitors (MetaWorkspace *workspace, MetaRectangle *area); void meta_workspace_activate (MetaWorkspace *workspace, guint32 timestamp); void meta_workspace_activate_with_focus (MetaWorkspace *workspace, MetaWindow *focus_this, guint32 timestamp); void meta_workspace_update_window_hints (MetaWorkspace *workspace); void meta_workspace_set_builtin_struts (MetaWorkspace *workspace, GSList *struts); MetaWorkspace *meta_workspace_get_neighbor (MetaWorkspace *workspace, MetaMotionDirection direction); #endif muffin-2.8.4/src/meta/atomnames.h0000664000175000017500000001252312623653707015625 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* * Copyright (C) 2001 Havoc Pennington * Copyright (C) 2002, 2003, 2004 Red Hat, Inc. * Copyright (C) 2003, 2004 Rob Adams * Copyright (C) 2004-2006 Elijah Newren * Copyright (C) 2008 Thomas Thurman * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ /** * \file atomnames.h A list of atom names. * * This is a list of the names of all the X atoms that Muffin uses. * Each is wrapped in a macro "item()" which is undefined here; the * idea is that when you need to make a big list of all the X atoms, * you can define item(), include this file, and then undefine it * again. * * If you also define EWMH_ATOMS_ONLY then you will only get _NET_WM_* * atoms rather than all of them. */ #ifndef item #error "item(x) must be defined when you include atomnames.h" #endif #ifndef EWMH_ATOMS_ONLY item(WM_PROTOCOLS) /* MUST BE FIRST */ item(WM_TAKE_FOCUS) item(WM_DELETE_WINDOW) item(WM_STATE) item(_MOTIF_WM_HINTS) item(WM_CHANGE_STATE) item(SM_CLIENT_ID) item(WM_CLIENT_LEADER) item(WM_WINDOW_ROLE) item(UTF8_STRING) item(WM_ICON_SIZE) item(_KWM_WIN_ICON) item(_MUFFIN_RELOAD_THEME_MESSAGE) item(_MUFFIN_SET_KEYBINDINGS_MESSAGE) item(_MUFFIN_TOGGLE_VERBOSE) item(_MUFFIN_HINTS) item(_GTK_THEME_VARIANT) item(_GTK_APPLICATION_ID) item(_GTK_UNIQUE_BUS_NAME) item(_GTK_APPLICATION_OBJECT_PATH) item(_GTK_WINDOW_OBJECT_PATH) item(_GTK_APP_MENU_OBJECT_PATH) item(_GTK_MENUBAR_OBJECT_PATH) item(_GTK_FRAME_EXTENTS) item(_GNOME_WM_KEYBINDINGS) item(_GNOME_PANEL_ACTION) item(_GNOME_PANEL_ACTION_RUN_DIALOG) item(_MUFFIN_SENTINEL) item(_MUFFIN_VERSION) item(WM_CLIENT_MACHINE) item(MANAGER) item(TARGETS) item(MULTIPLE) item(TIMESTAMP) item(VERSION) item(ATOM_PAIR) /* Oddities: These are used, and we need atoms for them, * but when we need all _NET_WM hints (i.e. when we're making * lists of which _NET_WM hints we support in order to advertise * it) we haven't historically listed them. I don't know what * the reason for this is. It may be a bug. */ item(_NET_WM_SYNC_REQUEST) item(_NET_WM_SYNC_REQUEST_COUNTER) item(_NET_WM_VISIBLE_NAME) item(_NET_WM_VISIBLE_ICON_NAME) item(_NET_SUPPORTING_WM_CHECK) /* But I suppose it's quite reasonable not to advertise using * _NET_SUPPORTED that we support _NET_SUPPORTED :) */ item(_NET_SUPPORTED) #endif /* !EWMH_ATOMS_ONLY */ /**************************************************************************/ item(_NET_WM_NAME) item(_NET_CLOSE_WINDOW) item(_NET_WM_STATE) item(_NET_WM_STATE_SHADED) item(_NET_WM_STATE_MAXIMIZED_HORZ) item(_NET_WM_STATE_MAXIMIZED_VERT) item(_NET_WM_STATE_TILED) item(_NET_WM_DESKTOP) item(_NET_NUMBER_OF_DESKTOPS) item(_NET_CURRENT_DESKTOP) item(_NET_WM_WINDOW_TYPE) item(_NET_WM_WINDOW_TYPE_DESKTOP) item(_NET_WM_WINDOW_TYPE_DOCK) item(_NET_WM_WINDOW_TYPE_TOOLBAR) item(_NET_WM_WINDOW_TYPE_MENU) item(_NET_WM_WINDOW_TYPE_UTILITY) item(_NET_WM_WINDOW_TYPE_SPLASH) item(_NET_WM_WINDOW_TYPE_DIALOG) item(_NET_WM_WINDOW_TYPE_DROPDOWN_MENU) item(_NET_WM_WINDOW_TYPE_POPUP_MENU) item(_NET_WM_WINDOW_TYPE_TOOLTIP) item(_NET_WM_WINDOW_TYPE_NOTIFICATION) item(_NET_WM_WINDOW_TYPE_COMBO) item(_NET_WM_WINDOW_TYPE_DND) item(_NET_WM_WINDOW_TYPE_NORMAL) item(_NET_WM_STATE_MODAL) item(_NET_CLIENT_LIST) item(_NET_CLIENT_LIST_STACKING) item(_NET_WM_STATE_SKIP_TASKBAR) item(_NET_WM_STATE_SKIP_PAGER) item(_NET_WM_WINDOW_TILE_INFO) item(_NET_WM_ICON_NAME) item(_NET_WM_ICON) item(_NET_WM_ICON_GEOMETRY) item(_NET_WM_MOVERESIZE) item(_NET_ACTIVE_WINDOW) item(_NET_WM_STRUT) item(_NET_WM_STATE_HIDDEN) item(_NET_WM_STATE_FULLSCREEN) item(_NET_WM_PING) item(_NET_WM_PID) item(_NET_WORKAREA) item(_NET_SHOWING_DESKTOP) item(_NET_DESKTOP_LAYOUT) item(_NET_DESKTOP_NAMES) item(_NET_WM_ALLOWED_ACTIONS) item(_NET_WM_ACTION_MOVE) item(_NET_WM_ACTION_RESIZE) item(_NET_WM_ACTION_SHADE) item(_NET_WM_ACTION_STICK) item(_NET_WM_ACTION_MAXIMIZE_HORZ) item(_NET_WM_ACTION_MAXIMIZE_VERT) item(_NET_WM_ACTION_CHANGE_DESKTOP) item(_NET_WM_ACTION_CLOSE) item(_NET_WM_STATE_ABOVE) item(_NET_WM_STATE_BELOW) item(_NET_STARTUP_ID) item(_NET_WM_STRUT_PARTIAL) item(_NET_WM_ACTION_FULLSCREEN) item(_NET_WM_ACTION_MINIMIZE) item(_NET_FRAME_EXTENTS) item(_GTK_SHOW_WINDOW_MENU) item(_NET_REQUEST_FRAME_EXTENTS) item(_NET_WM_USER_TIME) item(_NET_WM_STATE_DEMANDS_ATTENTION) item(_NET_MOVERESIZE_WINDOW) item(_NET_DESKTOP_GEOMETRY) item(_NET_DESKTOP_VIEWPORT) item(_NET_WM_USER_TIME_WINDOW) item(_NET_WM_ACTION_ABOVE) item(_NET_WM_ACTION_BELOW) item(_NET_WM_STATE_STICKY) item(_NET_WM_FULLSCREEN_MONITORS) item(_NET_WM_STATE_FOCUSED) item(_NET_WM_BYPASS_COMPOSITOR) item(_NET_WM_DONT_BYPASS_COMPOSITOR) item(_NET_WM_FRAME_DRAWN) item(_NET_WM_FRAME_TIMINGS) #if 0 /* We apparently never use: */ /* item(_NET_RESTACK_WINDOW) */ #endif /* eof atomnames.h */ muffin-2.8.4/src/meta/meta-window-actor.h0000664000175000017500000000551112623653707017201 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* * Copyright (C) 2008 Matthew Allum * Copyright (C) 2007 Iain Holmes * Based on xcompmgr - (c) 2003 Keith Packard * xfwm4 - (c) 2005-2007 Olivier Fourdan * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_WINDOW_ACTOR_H_ #define META_WINDOW_ACTOR_H_ #include #include #include /* * MetaWindowActor object (ClutterGroup sub-class) */ #define META_TYPE_WINDOW_ACTOR (meta_window_actor_get_type ()) #define META_WINDOW_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_WINDOW_ACTOR, MetaWindowActor)) #define META_WINDOW_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_WINDOW_ACTOR, MetaWindowActorClass)) #define META_IS_WINDOW_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_WINDOW_ACTOR)) #define META_IS_WINDOW_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_WINDOW_ACTOR)) #define META_WINDOW_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_WINDOW_ACTOR, MetaWindowActorClass)) typedef struct _MetaWindowActor MetaWindowActor; typedef struct _MetaWindowActorClass MetaWindowActorClass; typedef struct _MetaWindowActorPrivate MetaWindowActorPrivate; struct _MetaWindowActorClass { ClutterGroupClass parent_class; }; struct _MetaWindowActor { ClutterGroup parent; MetaWindowActorPrivate *priv; }; GType meta_window_actor_get_type (void); Window meta_window_actor_get_x_window (MetaWindowActor *self); gint meta_window_actor_get_workspace (MetaWindowActor *self); MetaWindow * meta_window_actor_get_meta_window (MetaWindowActor *self); ClutterActor * meta_window_actor_get_texture (MetaWindowActor *self); gboolean meta_window_actor_is_override_redirect (MetaWindowActor *self); const char * meta_window_actor_get_description (MetaWindowActor *self); gboolean meta_window_actor_showing_on_its_workspace (MetaWindowActor *self); gboolean meta_window_actor_is_destroyed (MetaWindowActor *self); #endif /* META_WINDOW_ACTOR_H */ muffin-2.8.4/src/meta/theme.h0000664000175000017500000000265612623653707014751 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* Metacity Theme Rendering */ /* * Copyright (C) 2001 Havoc Pennington * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_THEME_H #define META_THEME_H #include /** * MetaTheme: * */ typedef struct _MetaTheme MetaTheme; MetaTheme* meta_theme_get_current (void); void meta_theme_set_current (const char *name, gboolean force_reload); MetaTheme* meta_theme_new (void); void meta_theme_free (MetaTheme *theme); gboolean meta_theme_validate (MetaTheme *theme, GError **error); MetaTheme* meta_theme_load (const char *theme_name, GError **err); #endif muffin-2.8.4/src/meta/gradient.h0000664000175000017500000000516712623653707015444 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* Muffin gradient rendering */ /* * Copyright (C) 2001 Havoc Pennington, 99% copied from wrlib in * WindowMaker, Copyright (C) 1997-2000 Dan Pascu and Alfredo Kojima * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_GRADIENT_H #define META_GRADIENT_H #include #include typedef enum { META_GRADIENT_VERTICAL, META_GRADIENT_HORIZONTAL, META_GRADIENT_DIAGONAL, META_GRADIENT_LAST } MetaGradientType; GdkPixbuf* meta_gradient_create_simple (int width, int height, const GdkRGBA *from, const GdkRGBA *to, MetaGradientType style); GdkPixbuf* meta_gradient_create_multi (int width, int height, const GdkRGBA *colors, int n_colors, MetaGradientType style); GdkPixbuf* meta_gradient_create_interwoven (int width, int height, const GdkRGBA colors1[2], int thickness1, const GdkRGBA colors2[2], int thickness2); /* Generate an alpha gradient and multiply it with the existing alpha * channel of the given pixbuf */ void meta_gradient_add_alpha (GdkPixbuf *pixbuf, const guchar *alphas, int n_alphas, MetaGradientType type); #endif muffin-2.8.4/src/meta/compositor.h0000664000175000017500000002200112623653707016027 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* * Copyright (C) 2008 Iain Holmes * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_COMPOSITOR_H #define META_COMPOSITOR_H #include #include #include #include #include #include /** * MetaCompEffect: * @META_COMP_EFFECT_CREATE: The window is newly created * (also used for a window that was previously on a different * workspace and is changed to become visible on the active * workspace.) * @META_COMP_EFFECT_UNMINIMIZE: The window should be shown * as unminimizing from its icon geometry. * @META_COMP_EFFECT_DESTROY: The window is being destroyed * @META_COMP_EFFECT_MINIMIZE: The window should be shown * as minimizing to its icon geometry. * @META_COMP_EFFECT_NONE: No effect, the window should be * shown or hidden immediately. * * Indicates the appropriate effect to show the user for * meta_compositor_show_window() and meta_compositor_hide_window() */ typedef enum { META_COMP_EFFECT_CREATE, META_COMP_EFFECT_UNMINIMIZE, META_COMP_EFFECT_DESTROY, META_COMP_EFFECT_MINIMIZE, META_COMP_EFFECT_NONE } MetaCompEffect; MetaCompositor *meta_compositor_new (MetaDisplay *display); void meta_compositor_destroy (MetaCompositor *compositor); void meta_compositor_manage_screen (MetaCompositor *compositor, MetaScreen *screen); void meta_compositor_unmanage_screen (MetaCompositor *compositor, MetaScreen *screen); void meta_compositor_window_shape_changed (MetaCompositor *compositor, MetaWindow *window); gboolean meta_compositor_process_event (MetaCompositor *compositor, XEvent *event, MetaWindow *window); /* At a high-level, a window is not-visible or visible. When a * window is added (with add_window()) it is not visible. * show_window() indicates a transition from not-visible to * visible. Some of the reasons for this: * * - Window newly created * - Window is unminimized * - Window is moved to the current desktop * - Window was made sticky * * hide_window() indicates that the window has transitioned from * visible to not-visible. Some reasons include: * * - Window was destroyed * - Window is minimized * - Window is moved to a different desktop * - Window no longer sticky. * * Note that combinations are possible - a window might have first * been minimized and then moved to a different desktop. The * 'effect' parameter to show_window() and hide_window() is a hint * as to the appropriate effect to show the user and should not * be considered to be indicative of a state change. * * When the active workspace is changed, switch_workspace() is called * first, then show_window() and hide_window() are called individually * for each window affected, with an effect of META_COMP_EFFECT_NONE. * If hiding windows will affect the switch workspace animation, the * compositor needs to delay hiding the windows until the switch * workspace animation completes. * * maximize_window() and unmaximize_window() are transitions within * the visible state. The window is resized *before* the call, so * it may be necessary to readjust the display based on the old_rect * to start the animation. * * window_mapped() and window_unmapped() are notifications when the * toplevel window (frame or client window) is mapped or unmapped. * That is, when the result of meta_window_toplevel_is_mapped() * changes. The main use of this is to drop resources when a window * is unmapped. A window will always be mapped before show_window() * is called and will not be unmapped until after hide_window() is * called. If the live_hidden_windows preference is set, windows will * never be unmapped. */ void meta_compositor_add_window (MetaCompositor *compositor, MetaWindow *window); void meta_compositor_remove_window (MetaCompositor *compositor, MetaWindow *window); void meta_compositor_show_window (MetaCompositor *compositor, MetaWindow *window, MetaCompEffect effect); void meta_compositor_hide_window (MetaCompositor *compositor, MetaWindow *window, MetaCompEffect effect); void meta_compositor_switch_workspace (MetaCompositor *compositor, MetaScreen *screen, MetaWorkspace *from, MetaWorkspace *to, MetaMotionDirection direction); void meta_compositor_maximize_window (MetaCompositor *compositor, MetaWindow *window, MetaRectangle *old_rect, MetaRectangle *new_rect); void meta_compositor_unmaximize_window (MetaCompositor *compositor, MetaWindow *window, MetaRectangle *old_rect, MetaRectangle *new_rect); void meta_compositor_window_mapped (MetaCompositor *compositor, MetaWindow *window); void meta_compositor_window_unmapped (MetaCompositor *compositor, MetaWindow *window); void meta_compositor_sync_window_geometry (MetaCompositor *compositor, MetaWindow *window, gboolean did_placement); void meta_compositor_set_updates_frozen (MetaCompositor *compositor, MetaWindow *window, gboolean updates_frozen); void meta_compositor_queue_frame_drawn (MetaCompositor *compositor, MetaWindow *window, gboolean no_delay_frame); void meta_compositor_sync_stack (MetaCompositor *compositor, MetaScreen *screen, GList *stack); void meta_compositor_sync_screen_size (MetaCompositor *compositor, MetaScreen *screen, guint width, guint height); void meta_compositor_flash_screen (MetaCompositor *compositor, MetaScreen *screen); void meta_compositor_tile_window (MetaCompositor *compositor, MetaWindow *window, MetaRectangle *old_rect, MetaRectangle *new_rect); void meta_compositor_show_tile_preview (MetaCompositor *compositor, MetaScreen *screen, MetaWindow *window, MetaRectangle *tile_rect, int tile_monitor_number, guint snap_queued); void meta_compositor_hide_tile_preview (MetaCompositor *compositor, MetaScreen *screen); void meta_compositor_show_hud_preview (MetaCompositor *compositor, MetaScreen *screen, guint current_proximity_zone, MetaRectangle *work_area, guint snap_queued); void meta_compositor_hide_hud_preview (MetaCompositor *compositor, MetaScreen *screen); #endif /* META_COMPOSITOR_H */ muffin-2.8.4/src/meta/common.h0000664000175000017500000003127112623653707015132 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* Muffin common types shared by core.h and ui.h * * PLEASE KEEP IN SYNC WITH GSETTINGS SCHEMAS! */ /* * Copyright (C) 2001 Havoc Pennington * Copyright (C) 2005 Elijah Newren * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_COMMON_H #define META_COMMON_H /* Don't include core headers here */ #include #include #include /** * SECTION:common * @title: Common * @short_description: Muffin common types */ typedef struct _MetaResizePopup MetaResizePopup; typedef enum { META_FRAME_ALLOWS_DELETE = 1 << 0, META_FRAME_ALLOWS_MENU = 1 << 1, META_FRAME_ALLOWS_MINIMIZE = 1 << 2, META_FRAME_ALLOWS_MAXIMIZE = 1 << 3, META_FRAME_ALLOWS_LEFT_RESIZE = 1 << 4, META_FRAME_ALLOWS_RIGHT_RESIZE = 1 << 5, META_FRAME_ALLOWS_TOP_RESIZE = 1 << 6, META_FRAME_ALLOWS_BOTTOM_RESIZE = 1 << 7, META_FRAME_HAS_FOCUS = 1 << 8, META_FRAME_SHADED = 1 << 9, META_FRAME_STUCK = 1 << 10, META_FRAME_MAXIMIZED = 1 << 11, META_FRAME_ALLOWS_SHADE = 1 << 12, META_FRAME_ALLOWS_MOVE = 1 << 13, META_FRAME_FULLSCREEN = 1 << 14, META_FRAME_IS_FLASHING = 1 << 15, META_FRAME_ABOVE = 1 << 16, META_FRAME_TILED_LEFT = 1 << 17, META_FRAME_TILED_RIGHT = 1 << 18, META_FRAME_ALLOWS_VERTICAL_RESIZE = (META_FRAME_ALLOWS_TOP_RESIZE | META_FRAME_ALLOWS_BOTTOM_RESIZE), META_FRAME_ALLOWS_HORIZONTAL_RESIZE = (META_FRAME_ALLOWS_LEFT_RESIZE | META_FRAME_ALLOWS_RIGHT_RESIZE) } MetaFrameFlags; typedef enum { META_MENU_OP_NONE = 0, META_MENU_OP_DELETE = 1 << 0, META_MENU_OP_MINIMIZE = 1 << 1, META_MENU_OP_UNMAXIMIZE = 1 << 2, META_MENU_OP_MAXIMIZE = 1 << 3, META_MENU_OP_UNSHADE = 1 << 4, META_MENU_OP_SHADE = 1 << 5, META_MENU_OP_UNSTICK = 1 << 6, META_MENU_OP_STICK = 1 << 7, META_MENU_OP_WORKSPACES = 1 << 8, META_MENU_OP_MOVE = 1 << 9, META_MENU_OP_RESIZE = 1 << 10, META_MENU_OP_ABOVE = 1 << 11, META_MENU_OP_UNABOVE = 1 << 12, META_MENU_OP_MOVE_LEFT = 1 << 13, META_MENU_OP_MOVE_RIGHT = 1 << 14, META_MENU_OP_MOVE_UP = 1 << 15, META_MENU_OP_MOVE_DOWN = 1 << 16, META_MENU_OP_RECOVER = 1 << 17, META_MENU_OP_MOVE_NEW = 1 << 18 } MetaMenuOp; typedef struct _MetaWindowMenu MetaWindowMenu; typedef void (* MetaWindowMenuFunc) (MetaWindowMenu *menu, Display *xdisplay, Window client_xwindow, guint32 timestamp, MetaMenuOp op, int workspace, gpointer data); /* when changing this enum, there are various switch statements * you have to update */ typedef enum { META_GRAB_OP_NONE, /* Mouse ops */ META_GRAB_OP_MOVING, META_GRAB_OP_RESIZING_SE, META_GRAB_OP_RESIZING_S, META_GRAB_OP_RESIZING_SW, META_GRAB_OP_RESIZING_N, META_GRAB_OP_RESIZING_NE, META_GRAB_OP_RESIZING_NW, META_GRAB_OP_RESIZING_W, META_GRAB_OP_RESIZING_E, /* Keyboard ops */ META_GRAB_OP_KEYBOARD_MOVING, META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN, META_GRAB_OP_KEYBOARD_RESIZING_S, META_GRAB_OP_KEYBOARD_RESIZING_N, META_GRAB_OP_KEYBOARD_RESIZING_W, META_GRAB_OP_KEYBOARD_RESIZING_E, META_GRAB_OP_KEYBOARD_RESIZING_SE, META_GRAB_OP_KEYBOARD_RESIZING_NE, META_GRAB_OP_KEYBOARD_RESIZING_SW, META_GRAB_OP_KEYBOARD_RESIZING_NW, /* Alt+Tab */ META_GRAB_OP_KEYBOARD_TABBING_NORMAL, META_GRAB_OP_KEYBOARD_TABBING_DOCK, /* Alt+Esc */ META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL, META_GRAB_OP_KEYBOARD_ESCAPING_DOCK, META_GRAB_OP_KEYBOARD_ESCAPING_GROUP, /* Alt+F6 */ META_GRAB_OP_KEYBOARD_TABBING_GROUP, META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING, /* Frame button ops */ META_GRAB_OP_CLICKING_MINIMIZE, META_GRAB_OP_CLICKING_MAXIMIZE, META_GRAB_OP_CLICKING_UNMAXIMIZE, META_GRAB_OP_CLICKING_DELETE, META_GRAB_OP_CLICKING_MENU, META_GRAB_OP_CLICKING_SHADE, META_GRAB_OP_CLICKING_UNSHADE, META_GRAB_OP_CLICKING_ABOVE, META_GRAB_OP_CLICKING_UNABOVE, META_GRAB_OP_CLICKING_STICK, META_GRAB_OP_CLICKING_UNSTICK, /* Special grab op when the compositor asked for a grab */ META_GRAB_OP_COMPOSITOR } MetaGrabOp; typedef enum { META_CURSOR_DEFAULT, META_CURSOR_NORTH_RESIZE, META_CURSOR_SOUTH_RESIZE, META_CURSOR_WEST_RESIZE, META_CURSOR_EAST_RESIZE, META_CURSOR_SE_RESIZE, META_CURSOR_SW_RESIZE, META_CURSOR_NE_RESIZE, META_CURSOR_NW_RESIZE, META_CURSOR_MOVE_OR_RESIZE_WINDOW, META_CURSOR_BUSY } MetaCursor; typedef enum { META_FRAME_TYPE_NORMAL, META_FRAME_TYPE_DIALOG, META_FRAME_TYPE_MODAL_DIALOG, META_FRAME_TYPE_UTILITY, META_FRAME_TYPE_MENU, META_FRAME_TYPE_BORDER, META_FRAME_TYPE_ATTACHED, META_FRAME_TYPE_LAST } MetaFrameType; typedef enum { /* Create gratuitous divergence from regular * X mod bits, to be sure we find bugs */ META_VIRTUAL_SHIFT_MASK = 1 << 5, META_VIRTUAL_CONTROL_MASK = 1 << 6, META_VIRTUAL_ALT_MASK = 1 << 7, META_VIRTUAL_META_MASK = 1 << 8, META_VIRTUAL_SUPER_MASK = 1 << 9, META_VIRTUAL_HYPER_MASK = 1 << 10, META_VIRTUAL_MOD2_MASK = 1 << 11, META_VIRTUAL_MOD3_MASK = 1 << 12, META_VIRTUAL_MOD4_MASK = 1 << 13, META_VIRTUAL_MOD5_MASK = 1 << 14 } MetaVirtualModifier; /* Relative directions or sides seem to come up all over the place... */ /* FIXME: Replace * screen.[ch]:MetaScreenDirection, * workspace.[ch]:MetaMotionDirection, * with the use of MetaDirection. */ typedef enum { META_DIRECTION_LEFT = 1 << 0, META_DIRECTION_RIGHT = 1 << 1, META_DIRECTION_TOP = 1 << 2, META_DIRECTION_BOTTOM = 1 << 3, /* Some aliases for making code more readable for various circumstances. */ META_DIRECTION_UP = META_DIRECTION_TOP, META_DIRECTION_DOWN = META_DIRECTION_BOTTOM, /* A few more definitions using aliases */ META_DIRECTION_HORIZONTAL = META_DIRECTION_LEFT | META_DIRECTION_RIGHT, META_DIRECTION_VERTICAL = META_DIRECTION_UP | META_DIRECTION_DOWN, } MetaDirection; /* Negative to avoid conflicting with real workspace * numbers */ typedef enum { META_MOTION_UP = -1, META_MOTION_DOWN = -2, META_MOTION_LEFT = -3, META_MOTION_RIGHT = -4, /* These are only used for effects */ META_MOTION_UP_LEFT = -5, META_MOTION_UP_RIGHT = -6, META_MOTION_DOWN_LEFT = -7, META_MOTION_DOWN_RIGHT = -8, META_MOTION_NOT_EXIST_YET = -30 } MetaMotionDirection; /* Sometimes we want to talk about sides instead of directions; note * that the values must be as follows or meta_window_update_struts() * won't work. Using these values also is a safety blanket since * MetaDirection used to be used as a side. */ typedef enum { META_SIDE_LEFT = META_DIRECTION_LEFT, META_SIDE_RIGHT = META_DIRECTION_RIGHT, META_SIDE_TOP = META_DIRECTION_TOP, META_SIDE_BOTTOM = META_DIRECTION_BOTTOM } MetaSide; /* Function a window button can have. Note, you can't add stuff here * without extending the theme format to draw a new function and * breaking all existing themes. */ typedef enum { META_BUTTON_FUNCTION_MENU, META_BUTTON_FUNCTION_MINIMIZE, META_BUTTON_FUNCTION_MAXIMIZE, META_BUTTON_FUNCTION_CLOSE, META_BUTTON_FUNCTION_SHADE, META_BUTTON_FUNCTION_ABOVE, META_BUTTON_FUNCTION_STICK, META_BUTTON_FUNCTION_UNSHADE, META_BUTTON_FUNCTION_UNABOVE, META_BUTTON_FUNCTION_UNSTICK, META_BUTTON_FUNCTION_LAST } MetaButtonFunction; typedef enum { META_TILE_NONE, META_TILE_LEFT, META_TILE_RIGHT, META_TILE_ULC, META_TILE_LLC, META_TILE_URC, META_TILE_LRC, META_TILE_TOP, META_TILE_BOTTOM, META_TILE_MAXIMIZE } MetaTileMode; typedef enum { META_WINDOW_TILE_TYPE_NONE, META_WINDOW_TILE_TYPE_TILED, META_WINDOW_TILE_TYPE_SNAPPED } MetaWindowTileType; #define MAX_BUTTONS_PER_CORNER META_BUTTON_FUNCTION_LAST typedef struct _MetaButtonLayout MetaButtonLayout; struct _MetaButtonLayout { /* buttons in the group on the left side */ MetaButtonFunction left_buttons[MAX_BUTTONS_PER_CORNER]; gboolean left_buttons_has_spacer[MAX_BUTTONS_PER_CORNER]; /* buttons in the group on the right side */ MetaButtonFunction right_buttons[MAX_BUTTONS_PER_CORNER]; gboolean right_buttons_has_spacer[MAX_BUTTONS_PER_CORNER]; }; typedef struct _MetaFrameBorders MetaFrameBorders; struct _MetaFrameBorders { /* The frame border is made up of two pieces - an inner visible portion * and an outer portion that is invisible but responds to events. */ GtkBorder visible; GtkBorder invisible; /* For convenience, we have a "total" border which is equal to the sum * of the two borders above. */ GtkBorder total; }; /* sets all dimensions to zero */ void meta_frame_borders_clear (MetaFrameBorders *self); /* should investigate changing these to whatever most apps use */ #define META_ICON_WIDTH 32 #define META_ICON_HEIGHT 32 #define META_MINI_ICON_WIDTH 16 #define META_MINI_ICON_HEIGHT 16 #define META_DEFAULT_ICON_NAME "window" /* Main loop priorities determine when activity in the GLib * will take precendence over the others. Priorities are sometimes * used to enforce ordering: give A a higher priority than B if * A must occur before B. But that poses a problem since then * if A occurs frequently enough, B will never occur. * * Anything we want to occur more or less immediately should * have a priority of G_PRIORITY_DEFAULT. When we want to * coelesce multiple things together, the appropriate place to * do it is usually META_PRIORITY_BEFORE_REDRAW. * * Note that its usually better to use meta_later_add() rather * than calling g_idle_add() directly; this will make sure things * get run when added from a clutter event handler without * waiting for another repaint cycle. * * If something has a priority lower than the redraw priority * (such as a default priority idle), then it may be arbitrarily * delayed. This happens if the screen is updating rapidly: we * are spending all our time either redrawing or waiting for a * vblank-synced buffer swap. (When X is improved to allow * clutter to do the buffer-swap asychronously, this will get * better.) */ /* G_PRIORITY_DEFAULT: * events * many timeouts */ /* GTK_PRIORITY_RESIZE: (G_PRIORITY_HIGH_IDLE + 10) */ #define META_PRIORITY_RESIZE (G_PRIORITY_HIGH_IDLE + 15) /* GTK_PRIORITY_REDRAW: (G_PRIORITY_HIGH_IDLE + 20) */ #define META_PRIORITY_BEFORE_REDRAW (G_PRIORITY_HIGH_IDLE + 40) /* calc-showing idle * update-icon idle */ /* CLUTTER_PRIORITY_REDRAW: (G_PRIORITY_HIGH_IDLE + 50) */ #define META_PRIORITY_REDRAW (G_PRIORITY_HIGH_IDLE + 50) /* ==== Anything below here can be starved arbitrarily ==== */ /* G_PRIORITY_DEFAULT_IDLE: * Muffin plugin unloading */ #define META_PRIORITY_PREFS_NOTIFY (G_PRIORITY_DEFAULT_IDLE + 10) /************************************************************/ #define POINT_IN_RECT(xcoord, ycoord, rect) \ ((xcoord) >= (rect).x && \ (xcoord) < ((rect).x + (rect).width) && \ (ycoord) >= (rect).y && \ (ycoord) < ((rect).y + (rect).height)) /* * Layers a window can be in. * These MUST be in the order of stacking. */ typedef enum { META_LAYER_DESKTOP = 0, META_LAYER_BOTTOM = 1, META_LAYER_NORMAL = 2, META_LAYER_TOP = 4, /* Same as DOCK; see EWMH and bug 330717 */ META_LAYER_DOCK = 4, META_LAYER_FULLSCREEN = 5, META_LAYER_FOCUSED_WINDOW = 6, META_LAYER_OVERRIDE_REDIRECT = 7, META_LAYER_LAST = 8 } MetaStackLayer; /* * Placement mode */ typedef enum { META_PLACEMENT_MODE_AUTOMATIC, META_PLACEMENT_MODE_POINTER, META_PLACEMENT_MODE_MANUAL, META_PLACEMENT_MODE_CENTER } MetaPlacementMode; #endif muffin-2.8.4/src/meta/prefs.h0000664000175000017500000003142412623653707014761 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* Muffin preferences */ /* * Copyright (C) 2001 Havoc Pennington * Copyright (C) 2006 Elijah Newren * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_PREFS_H #define META_PREFS_H /* This header is a "common" one between the UI and core side */ #include #include #include #include #include /* Keep in sync with GSettings schemas! */ typedef enum { META_PREF_MOUSE_BUTTON_MODS, META_PREF_FOCUS_MODE, META_PREF_FOCUS_NEW_WINDOWS, META_PREF_ATTACH_MODAL_DIALOGS, META_PREF_RAISE_ON_CLICK, META_PREF_ACTION_DOUBLE_CLICK_TITLEBAR, META_PREF_ACTION_MIDDLE_CLICK_TITLEBAR, META_PREF_ACTION_RIGHT_CLICK_TITLEBAR, META_PREF_ACTION_SCROLL_WHEEL_TITLEBAR, META_PREF_AUTO_RAISE, META_PREF_AUTO_RAISE_DELAY, META_PREF_THEME, META_PREF_TITLEBAR_FONT, META_PREF_NUM_WORKSPACES, META_PREF_DYNAMIC_WORKSPACES, META_PREF_UNREDIRECT_FULLSCREEN_WINDOWS, META_PREF_APPLICATION_BASED, META_PREF_KEYBINDINGS, META_PREF_DISABLE_WORKAROUNDS, META_PREF_BUTTON_LAYOUT, META_PREF_WORKSPACE_NAMES, META_PREF_WORKSPACE_CYCLE, META_PREF_VISUAL_BELL, META_PREF_AUDIBLE_BELL, META_PREF_VISUAL_BELL_TYPE, META_PREF_GNOME_ACCESSIBILITY, META_PREF_GNOME_ANIMATIONS, META_PREF_CURSOR_THEME, META_PREF_CURSOR_SIZE, META_PREF_RESIZE_WITH_RIGHT_BUTTON, META_PREF_EDGE_TILING, META_PREF_FORCE_FULLSCREEN, META_PREF_LIVE_HIDDEN_WINDOWS, META_PREF_WORKSPACES_ONLY_ON_PRIMARY, META_PREF_DRAGGABLE_BORDER_WIDTH, META_PREF_TILE_HUD_THRESHOLD, META_PREF_RESIZE_THRESHOLD, META_PREF_SNAP_MODIFIER, META_PREF_LEGACY_SNAP, META_PREF_INVERT_WORKSPACE_FLIP_DIRECTION, META_PREF_TILE_MAXIMIZE, META_PREF_PLACEMENT_MODE, META_PREF_MIN_WIN_OPACITY, META_PREF_MOUSE_ZOOM_ENABLED, META_PREF_MOUSE_BUTTON_ZOOM_MODS } MetaPreference; typedef void (* MetaPrefsChangedFunc) (MetaPreference pref, gpointer data); void meta_prefs_add_listener (MetaPrefsChangedFunc func, gpointer data); void meta_prefs_remove_listener (MetaPrefsChangedFunc func, gpointer data); void meta_prefs_init (void); void meta_prefs_override_preference_schema (const char *key, const char *schema); const char* meta_preference_to_string (MetaPreference pref); MetaVirtualModifier meta_prefs_get_mouse_button_mods (void); MetaVirtualModifier meta_prefs_get_mouse_button_zoom_mods (void); gboolean meta_prefs_get_mouse_zoom_enabled (void); guint meta_prefs_get_mouse_button_resize (void); guint meta_prefs_get_mouse_button_menu (void); CDesktopFocusMode meta_prefs_get_focus_mode (void); CDesktopFocusNewWindows meta_prefs_get_focus_new_windows (void); gboolean meta_prefs_get_attach_modal_dialogs (void); gboolean meta_prefs_get_raise_on_click (void); const char* meta_prefs_get_theme (void); /* returns NULL if GTK default should be used */ const PangoFontDescription* meta_prefs_get_titlebar_font (void); int meta_prefs_get_num_workspaces (void); gboolean meta_prefs_get_workspace_cycle (void); gboolean meta_prefs_get_dynamic_workspaces (void); gboolean meta_prefs_get_unredirect_fullscreen_windows (void); gboolean meta_prefs_get_application_based (void); gboolean meta_prefs_get_disable_workarounds (void); gboolean meta_prefs_get_auto_raise (void); int meta_prefs_get_auto_raise_delay (void); gboolean meta_prefs_get_gnome_accessibility (void); gboolean meta_prefs_get_gnome_animations (void); gboolean meta_prefs_get_edge_tiling (void); const char* meta_prefs_get_screenshot_command (void); const char* meta_prefs_get_window_screenshot_command (void); const char* meta_prefs_get_terminal_command (void); void meta_prefs_get_button_layout (MetaButtonLayout *button_layout); /* Double, right, middle click can be configured to any titlebar meta-action */ CDesktopTitlebarAction meta_prefs_get_action_double_click_titlebar (void); CDesktopTitlebarAction meta_prefs_get_action_middle_click_titlebar (void); CDesktopTitlebarAction meta_prefs_get_action_right_click_titlebar (void); CDesktopTitlebarScrollAction meta_prefs_get_action_scroll_wheel_titlebar (void); void meta_prefs_set_num_workspaces (int n_workspaces); const char* meta_prefs_get_workspace_name (int i); void meta_prefs_change_workspace_name (int i, const char *name); const char* meta_prefs_get_cursor_theme (void); int meta_prefs_get_cursor_size (void); gboolean meta_prefs_get_compositing_manager (void); gboolean meta_prefs_get_force_fullscreen (void); /* * Sets whether the compositor is turned on. * * \param whether TRUE to turn on, FALSE to turn off */ void meta_prefs_set_compositing_manager (gboolean whether); void meta_prefs_set_force_fullscreen (gboolean whether); gboolean meta_prefs_get_live_hidden_windows (void); void meta_prefs_set_live_hidden_windows (gboolean whether); gboolean meta_prefs_get_workspaces_only_on_primary (void); int meta_prefs_get_draggable_border_width (void); int meta_prefs_get_tile_hud_threshold (void); int meta_prefs_get_resize_threshold (void); unsigned int * meta_prefs_get_snap_modifier (void); gboolean meta_prefs_get_legacy_snap (void); gboolean meta_prefs_get_invert_flip_direction (void); gboolean meta_prefs_get_tile_maximize (void); gint meta_prefs_get_min_win_opacity (void); gint meta_prefs_get_ui_scale (void); /* XXX FIXME This should be x-macroed, but isn't yet because it would be * difficult (or perhaps impossible) to add the suffixes using the current * system. It needs some more thought, perhaps after the current system * evolves a little. */ typedef enum _MetaKeyBindingAction { META_KEYBINDING_ACTION_NONE = -1, META_KEYBINDING_ACTION_WORKSPACE_1, META_KEYBINDING_ACTION_WORKSPACE_2, META_KEYBINDING_ACTION_WORKSPACE_3, META_KEYBINDING_ACTION_WORKSPACE_4, META_KEYBINDING_ACTION_WORKSPACE_5, META_KEYBINDING_ACTION_WORKSPACE_6, META_KEYBINDING_ACTION_WORKSPACE_7, META_KEYBINDING_ACTION_WORKSPACE_8, META_KEYBINDING_ACTION_WORKSPACE_9, META_KEYBINDING_ACTION_WORKSPACE_10, META_KEYBINDING_ACTION_WORKSPACE_11, META_KEYBINDING_ACTION_WORKSPACE_12, META_KEYBINDING_ACTION_WORKSPACE_LEFT, META_KEYBINDING_ACTION_WORKSPACE_RIGHT, META_KEYBINDING_ACTION_WORKSPACE_UP, META_KEYBINDING_ACTION_WORKSPACE_DOWN, META_KEYBINDING_ACTION_SWITCH_GROUP, META_KEYBINDING_ACTION_SWITCH_GROUP_BACKWARD, META_KEYBINDING_ACTION_SWITCH_WINDOWS, META_KEYBINDING_ACTION_SWITCH_WINDOWS_BACKWARD, META_KEYBINDING_ACTION_SWITCH_PANELS, META_KEYBINDING_ACTION_SWITCH_PANELS_BACKWARD, META_KEYBINDING_ACTION_CYCLE_GROUP, META_KEYBINDING_ACTION_CYCLE_GROUP_BACKWARD, META_KEYBINDING_ACTION_CYCLE_WINDOWS, META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD, META_KEYBINDING_ACTION_CYCLE_PANELS, META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD, META_KEYBINDING_ACTION_TAB_POPUP_SELECT, META_KEYBINDING_ACTION_TAB_POPUP_CANCEL, META_KEYBINDING_ACTION_SHOW_DESKTOP, META_KEYBINDING_ACTION_PANEL_RUN_DIALOG, META_KEYBINDING_ACTION_TOGGLE_RECORDING, META_KEYBINDING_ACTION_SET_SPEW_MARK, META_KEYBINDING_ACTION_ACTIVATE_WINDOW_MENU, META_KEYBINDING_ACTION_TOGGLE_FULLSCREEN, META_KEYBINDING_ACTION_TOGGLE_MAXIMIZED, META_KEYBINDING_ACTION_PUSH_TILE_LEFT, META_KEYBINDING_ACTION_PUSH_TILE_RIGHT, META_KEYBINDING_ACTION_PUSH_TILE_UP, META_KEYBINDING_ACTION_PUSH_TILE_DOWN, META_KEYBINDING_ACTION_PUSH_SNAP_LEFT, META_KEYBINDING_ACTION_PUSH_SNAP_RIGHT, META_KEYBINDING_ACTION_PUSH_SNAP_UP, META_KEYBINDING_ACTION_PUSH_SNAP_DOWN, META_KEYBINDING_ACTION_TOGGLE_ABOVE, META_KEYBINDING_ACTION_MAXIMIZE, META_KEYBINDING_ACTION_UNMAXIMIZE, META_KEYBINDING_ACTION_TOGGLE_SHADED, META_KEYBINDING_ACTION_MINIMIZE, META_KEYBINDING_ACTION_CLOSE, META_KEYBINDING_ACTION_BEGIN_MOVE, META_KEYBINDING_ACTION_BEGIN_RESIZE, META_KEYBINDING_ACTION_TOGGLE_ON_ALL_WORKSPACES, META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_1, META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_2, META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_3, META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_4, META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_5, META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_6, META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_7, META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_8, META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_9, META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_10, META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_11, META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_12, META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_LEFT, META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_RIGHT, META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_UP, META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_DOWN, META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_NEW, META_KEYBINDING_ACTION_MOVE_TO_MONITOR_LEFT, META_KEYBINDING_ACTION_MOVE_TO_MONITOR_RIGHT, META_KEYBINDING_ACTION_MOVE_TO_MONITOR_DOWN, META_KEYBINDING_ACTION_MOVE_TO_MONITOR_UP, META_KEYBINDING_ACTION_RAISE_OR_LOWER, META_KEYBINDING_ACTION_RAISE, META_KEYBINDING_ACTION_LOWER, META_KEYBINDING_ACTION_MAXIMIZE_VERTICALLY, META_KEYBINDING_ACTION_MAXIMIZE_HORIZONTALLY, META_KEYBINDING_ACTION_MOVE_TO_CORNER_NW, META_KEYBINDING_ACTION_MOVE_TO_CORNER_NE, META_KEYBINDING_ACTION_MOVE_TO_CORNER_SW, META_KEYBINDING_ACTION_MOVE_TO_CORNER_SE, META_KEYBINDING_ACTION_MOVE_TO_SIDE_N, META_KEYBINDING_ACTION_MOVE_TO_SIDE_S, META_KEYBINDING_ACTION_MOVE_TO_SIDE_E, META_KEYBINDING_ACTION_MOVE_TO_SIDE_W, META_KEYBINDING_ACTION_MOVE_TO_CENTER, META_KEYBINDING_ACTION_INCREASE_OPACITY, META_KEYBINDING_ACTION_DECREASE_OPACITY, META_KEYBINDING_ACTION_CUSTOM, META_KEYBINDING_ACTION_LAST } MetaKeyBindingAction; typedef enum { META_KEY_BINDING_NONE, META_KEY_BINDING_PER_WINDOW = 1 << 0, META_KEY_BINDING_BUILTIN = 1 << 1, META_KEY_BINDING_REVERSES = 1 << 2, META_KEY_BINDING_IS_REVERSED = 1 << 3 } MetaKeyBindingFlags; typedef struct { unsigned int keysym; unsigned int keycode; MetaVirtualModifier modifiers; } MetaKeyCombo; /** * MetaKeyHandlerFunc: * @event: (type gpointer): * */ typedef void (* MetaKeyHandlerFunc) (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, MetaKeyBinding *binding, gpointer user_data); typedef struct _MetaKeyHandler MetaKeyHandler; typedef struct { char *name; char *schema; MetaKeyBindingAction action; /* * A list of MetaKeyCombos. Each of them is bound to * this keypref. If one has keysym==modifiers==0, it is * ignored. */ GSList *bindings; /* for keybindings that can have shift or not like Alt+Tab */ gboolean add_shift:1; /* for keybindings that apply only to a window */ gboolean per_window:1; /* for keybindings not added with meta_display_add_keybinding() */ gboolean builtin:1; } MetaKeyPref; GType meta_key_binding_get_type (void); GList *meta_prefs_get_keybindings (void); MetaKeyBindingAction meta_prefs_get_keybinding_action (const char *name); void meta_prefs_get_window_binding (const char *name, unsigned int *keysym, MetaVirtualModifier *modifiers); gboolean meta_prefs_get_visual_bell (void); gboolean meta_prefs_bell_is_audible (void); CDesktopVisualBellType meta_prefs_get_visual_bell_type (void); MetaPlacementMode meta_prefs_get_placement_mode (void); #endif muffin-2.8.4/src/meta/util.h0000664000175000017500000001232012623653707014611 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* Muffin utilities */ /* * Copyright (C) 2001 Havoc Pennington * Copyright (C) 2005 Elijah Newren * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_UTIL_H #define META_UTIL_H #include #include #include gboolean meta_is_verbose (void); void meta_set_verbose (gboolean setting); gboolean meta_is_debugging (void); void meta_set_debugging (gboolean setting); gboolean meta_is_syncing (void); void meta_set_syncing (gboolean setting); void meta_set_replace_current_wm (gboolean setting); void meta_debug_spew_real (const char *format, ...) G_GNUC_PRINTF (1, 2); void meta_verbose_real (const char *format, ...) G_GNUC_PRINTF (1, 2); void meta_bug (const char *format, ...) G_GNUC_PRINTF (1, 2); void meta_warning (const char *format, ...) G_GNUC_PRINTF (1, 2); void meta_fatal (const char *format, ...) G_GNUC_PRINTF (1, 2); typedef enum { META_DEBUG_VERBOSE = -1, META_DEBUG_FOCUS = 1 << 0, META_DEBUG_WORKAREA = 1 << 1, META_DEBUG_STACK = 1 << 2, META_DEBUG_THEMES = 1 << 3, META_DEBUG_SM = 1 << 4, META_DEBUG_EVENTS = 1 << 5, META_DEBUG_WINDOW_STATE = 1 << 6, META_DEBUG_WINDOW_OPS = 1 << 7, META_DEBUG_GEOMETRY = 1 << 8, META_DEBUG_PLACEMENT = 1 << 9, META_DEBUG_PING = 1 << 10, META_DEBUG_XINERAMA = 1 << 11, META_DEBUG_KEYBINDINGS = 1 << 12, META_DEBUG_SYNC = 1 << 13, META_DEBUG_ERRORS = 1 << 14, META_DEBUG_STARTUP = 1 << 15, META_DEBUG_PREFS = 1 << 16, META_DEBUG_GROUPS = 1 << 17, META_DEBUG_RESIZING = 1 << 18, META_DEBUG_SHAPES = 1 << 19, META_DEBUG_COMPOSITOR = 1 << 20, META_DEBUG_EDGE_RESISTANCE = 1 << 21 } MetaDebugTopic; void meta_topic_real (MetaDebugTopic topic, const char *format, ...) G_GNUC_PRINTF (2, 3); void meta_add_verbose_topic (MetaDebugTopic topic); void meta_remove_verbose_topic (MetaDebugTopic topic); void meta_push_no_msg_prefix (void); void meta_pop_no_msg_prefix (void); gint meta_unsigned_long_equal (gconstpointer v1, gconstpointer v2); guint meta_unsigned_long_hash (gconstpointer v); void meta_print_backtrace (void); const char* meta_frame_type_to_string (MetaFrameType type); const char* meta_gravity_to_string (int gravity); #include #define _(x) dgettext (GETTEXT_PACKAGE, x) #define N_(x) x char* meta_g_utf8_strndup (const gchar *src, gsize n); void meta_free_gslist_and_elements (GSList *list_to_deep_free); GPid meta_show_dialog (const char *type, const char *message, const char *timeout, const char *display, const char *ok_text, const char *cancel_text, const int transient_for, GSList *columns, GSList *entries); /* To disable verbose mode, we make these functions into no-ops */ #ifdef WITH_VERBOSE_MODE #define meta_debug_spew meta_debug_spew_real #define meta_verbose meta_verbose_real #define meta_topic meta_topic_real #else # ifdef G_HAVE_ISO_VARARGS # define meta_debug_spew(...) # define meta_verbose(...) # define meta_topic(...) # elif defined(G_HAVE_GNUC_VARARGS) # define meta_debug_spew(format...) # define meta_verbose(format...) # define meta_topic(format...) # else # error "This compiler does not support varargs macros and thus verbose mode can't be disabled meaningfully" # endif #endif /* !WITH_VERBOSE_MODE */ /** * MetaLaterType: * @META_LATER_RESIZE: call in a resize processing phase that is done * before GTK+ repainting (including window borders) is done. * @META_LATER_BEFORE_REDRAW: call before the stage is redrawn * @META_LATER_IDLE: call at a very low priority (can be blocked * by running animations or redrawing applications) **/ typedef enum { META_LATER_RESIZE, META_LATER_BEFORE_REDRAW, META_LATER_IDLE } MetaLaterType; guint meta_later_add (MetaLaterType when, GSourceFunc func, gpointer data, GDestroyNotify notify); void meta_later_remove (guint later_id); #endif /* META_UTIL_H */ muffin-2.8.4/src/stock_maximize.png0000664000175000017500000000024612623653707016275 0ustar fabiofabioPNG  IHDRabKGD pHYs  ~tIMElz9h3IDATxc`T}LbX=- '́004 b-IENDB`muffin-2.8.4/src/ui/0000775000175000017500000000000012623653707013154 5ustar fabiofabiomuffin-2.8.4/src/ui/menu.h0000664000175000017500000000443512623653707014277 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* Muffin window menu */ /* * Copyright (C) 2001 Havoc Pennington * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_MENU_H #define META_MENU_H #include #include "frames.h" /* Stock icons */ #define METACITY_STOCK_DELETE "metacity-delete" #define METACITY_STOCK_MINIMIZE "metacity-minimize" #define METACITY_STOCK_MAXIMIZE "metacity-maximize" struct _MetaWindowMenu { MetaFrames *frames; Window client_xwindow; GtkWidget *menu; MetaWindowMenuFunc func; gpointer data; MetaMenuOp ops; MetaMenuOp insensitive; }; MetaWindowMenu* meta_window_menu_new (MetaFrames *frames, MetaMenuOp ops, MetaMenuOp insensitive, Window client_xwindow, unsigned long active_workspace, int n_workspaces, MetaWindowMenuFunc func, gpointer data); void meta_window_menu_popup (MetaWindowMenu *menu, int root_x, int root_y, int button, guint32 timestamp); void meta_window_menu_free (MetaWindowMenu *menu); #endif muffin-2.8.4/src/ui/gradient.c0000664000175000017500000005703112623653707015123 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* Metacity gradient rendering */ /* * Copyright (C) 2001 Havoc Pennington, 99% copied from wrlib in * WindowMaker, Copyright (C) 1997-2000 Dan Pascu and Alfredo Kojima * Copyright (C) 2005 Elijah Newren * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #include #include #include /* This is all Alfredo's and Dan's usual very nice WindowMaker code, * slightly GTK-ized */ static GdkPixbuf* meta_gradient_create_horizontal (int width, int height, const GdkRGBA *from, const GdkRGBA *to); static GdkPixbuf* meta_gradient_create_vertical (int width, int height, const GdkRGBA *from, const GdkRGBA *to); static GdkPixbuf* meta_gradient_create_diagonal (int width, int height, const GdkRGBA *from, const GdkRGBA *to); static GdkPixbuf* meta_gradient_create_multi_horizontal (int width, int height, const GdkRGBA *colors, int count); static GdkPixbuf* meta_gradient_create_multi_vertical (int width, int height, const GdkRGBA *colors, int count); static GdkPixbuf* meta_gradient_create_multi_diagonal (int width, int height, const GdkRGBA *colors, int count); /* Used as the destroy notification function for gdk_pixbuf_new() */ static void free_buffer (guchar *pixels, gpointer data) { g_free (pixels); } static GdkPixbuf* blank_pixbuf (int width, int height, gboolean no_padding) { guchar *buf; int rowstride; g_return_val_if_fail (width > 0, NULL); g_return_val_if_fail (height > 0, NULL); if (no_padding) rowstride = width * 3; else /* Always align rows to 32-bit boundaries */ rowstride = 4 * ((3 * width + 3) / 4); buf = g_try_malloc (height * rowstride); if (!buf) return NULL; return gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB, FALSE, 8, width, height, rowstride, free_buffer, NULL); } /** * meta_gradient_create_simple: * @width: Width in pixels * @height: Height in pixels * @from: Starting color * @to: Ending color * @style: Gradient style * * Returns: (transfer full): A new linear gradient */ GdkPixbuf* meta_gradient_create_simple (int width, int height, const GdkRGBA *from, const GdkRGBA *to, MetaGradientType style) { switch (style) { case META_GRADIENT_HORIZONTAL: return meta_gradient_create_horizontal (width, height, from, to); case META_GRADIENT_VERTICAL: return meta_gradient_create_vertical (width, height, from, to); case META_GRADIENT_DIAGONAL: return meta_gradient_create_diagonal (width, height, from, to); case META_GRADIENT_LAST: break; } g_assert_not_reached (); return NULL; } /** * meta_gradient_create_multi: * @width: Width in pixels * @height: Height in pixels * @colors: (array length=n_colors): Array of colors * @n_colors: Number of colors * @style: Gradient style * * Returns: (transfer full): A new multi-step linear gradient */ GdkPixbuf* meta_gradient_create_multi (int width, int height, const GdkRGBA *colors, int n_colors, MetaGradientType style) { if (n_colors > 2) { switch (style) { case META_GRADIENT_HORIZONTAL: return meta_gradient_create_multi_horizontal (width, height, colors, n_colors); case META_GRADIENT_VERTICAL: return meta_gradient_create_multi_vertical (width, height, colors, n_colors); case META_GRADIENT_DIAGONAL: return meta_gradient_create_multi_diagonal (width, height, colors, n_colors); case META_GRADIENT_LAST: g_assert_not_reached (); break; } } else if (n_colors > 1) { return meta_gradient_create_simple (width, height, &colors[0], &colors[1], style); } else if (n_colors > 0) { return meta_gradient_create_simple (width, height, &colors[0], &colors[0], style); } g_assert_not_reached (); return NULL; } /** * meta_gradient_create_interwoven: (skip) * * Interwoven essentially means we have two vertical gradients, * cut into horizontal strips of the given thickness, and then the strips * are alternated. I'm not sure what it's good for, just copied since * WindowMaker had it. */ GdkPixbuf* meta_gradient_create_interwoven (int width, int height, const GdkRGBA colors1[2], int thickness1, const GdkRGBA colors2[2], int thickness2) { int i, j, k, l, ll; long r1, g1, b1, dr1, dg1, db1; long r2, g2, b2, dr2, dg2, db2; GdkPixbuf *pixbuf; unsigned char *ptr; unsigned char *pixels; int rowstride; pixbuf = blank_pixbuf (width, height, FALSE); if (pixbuf == NULL) return NULL; pixels = gdk_pixbuf_get_pixels (pixbuf); rowstride = gdk_pixbuf_get_rowstride (pixbuf); r1 = (long)(colors1[0].red*0xffffff); g1 = (long)(colors1[0].green*0xffffff); b1 = (long)(colors1[0].blue*0xffffff); r2 = (long)(colors2[0].red*0xffffff); g2 = (long)(colors2[0].green*0xffffff); b2 = (long)(colors2[0].blue*0xffffff); dr1 = ((colors1[1].red-colors1[0].red)*0xffffff)/(int)height; dg1 = ((colors1[1].green-colors1[0].green)*0xffffff)/(int)height; db1 = ((colors1[1].blue-colors1[0].blue)*0xffffff)/(int)height; dr2 = ((colors2[1].red-colors2[0].red)*0xffffff)/(int)height; dg2 = ((colors2[1].green-colors2[0].green)*0xffffff)/(int)height; db2 = ((colors2[1].blue-colors2[0].blue)*0xffffff)/(int)height; for (i=0,k=0,l=0,ll=thickness1; i>16); ptr[1] = (unsigned char) (g1>>16); ptr[2] = (unsigned char) (b1>>16); } else { ptr[0] = (unsigned char) (r2>>16); ptr[1] = (unsigned char) (g2>>16); ptr[2] = (unsigned char) (b2>>16); } for (j=1; j <= width/2; j *= 2) memcpy (&(ptr[j*3]), ptr, j*3); memcpy (&(ptr[j*3]), ptr, (width - j)*3); if (++l == ll) { if (k == 0) { k = 1; ll = thickness2; } else { k = 0; ll = thickness1; } l = 0; } r1+=dr1; g1+=dg1; b1+=db1; r2+=dr2; g2+=dg2; b2+=db2; } return pixbuf; } /* *---------------------------------------------------------------------- * meta_gradient_create_horizontal-- * Renders a horizontal linear gradient of the specified size in the * GdkPixbuf format with a border of the specified type. * * Returns: * A 24bit GdkPixbuf with the gradient (no alpha channel). * * Side effects: * None *---------------------------------------------------------------------- */ static GdkPixbuf* meta_gradient_create_horizontal (int width, int height, const GdkRGBA *from, const GdkRGBA *to) { int i; long r, g, b, dr, dg, db; GdkPixbuf *pixbuf; unsigned char *ptr; unsigned char *pixels; int r0, g0, b0; int rf, gf, bf; int rowstride; pixbuf = blank_pixbuf (width, height, FALSE); if (pixbuf == NULL) return NULL; pixels = gdk_pixbuf_get_pixels (pixbuf); ptr = pixels; rowstride = gdk_pixbuf_get_rowstride (pixbuf); r0 = (guchar) (from->red * 0xff); g0 = (guchar) (from->green * 0xff); b0 = (guchar) (from->blue * 0xff); rf = (guchar) (to->red * 0xff); gf = (guchar) (to->green * 0xff); bf = (guchar) (to->blue * 0xff); r = r0 << 16; g = g0 << 16; b = b0 << 16; dr = ((rf-r0)<<16)/(int)width; dg = ((gf-g0)<<16)/(int)width; db = ((bf-b0)<<16)/(int)width; /* render the first line */ for (i=0; i>16); *(ptr++) = (unsigned char)(g>>16); *(ptr++) = (unsigned char)(b>>16); r += dr; g += dg; b += db; } /* copy the first line to the other lines */ for (i=1; ired * 0xff); g0 = (guchar) (from->green * 0xff); b0 = (guchar) (from->blue * 0xff); rf = (guchar) (to->red * 0xff); gf = (guchar) (to->green * 0xff); bf = (guchar) (to->blue * 0xff); r = r0<<16; g = g0<<16; b = b0<<16; dr = ((rf-r0)<<16)/(int)height; dg = ((gf-g0)<<16)/(int)height; db = ((bf-b0)<<16)/(int)height; for (i=0; i>16); ptr[1] = (unsigned char)(g>>16); ptr[2] = (unsigned char)(b>>16); for (j=1; j <= width/2; j *= 2) memcpy (&(ptr[j*3]), ptr, j*3); memcpy (&(ptr[j*3]), ptr, (width - j)*3); r+=dr; g+=dg; b+=db; } return pixbuf; } /* *---------------------------------------------------------------------- * meta_gradient_create_diagonal-- * Renders a diagonal linear gradient of the specified size in the * GdkPixbuf format with a border of the specified type. * * Returns: * A 24bit GdkPixbuf with the gradient (no alpha channel). * * Side effects: * None *---------------------------------------------------------------------- */ static GdkPixbuf* meta_gradient_create_diagonal (int width, int height, const GdkRGBA *from, const GdkRGBA *to) { GdkPixbuf *pixbuf, *tmp; int j; float a, offset; unsigned char *ptr; unsigned char *pixels; int rowstride; if (width == 1) return meta_gradient_create_vertical (width, height, from, to); else if (height == 1) return meta_gradient_create_horizontal (width, height, from, to); pixbuf = blank_pixbuf (width, height, FALSE); if (pixbuf == NULL) return NULL; pixels = gdk_pixbuf_get_pixels (pixbuf); rowstride = gdk_pixbuf_get_rowstride (pixbuf); tmp = meta_gradient_create_horizontal (2*width-1, 1, from, to); if (!tmp) { g_object_unref (G_OBJECT (pixbuf)); return NULL; } ptr = gdk_pixbuf_get_pixels (tmp); a = ((float)(width - 1))/((float)(height - 1)); width = width * 3; /* copy the first line to the other lines with corresponding offset */ for (j=0, offset=0.0; j 2, NULL); pixbuf = blank_pixbuf (width, height, FALSE); if (pixbuf == NULL) return NULL; pixels = gdk_pixbuf_get_pixels (pixbuf); rowstride = gdk_pixbuf_get_rowstride (pixbuf); ptr = pixels; if (count > width) count = width; if (count > 1) width2 = width/(count-1); else width2 = width; k = 0; r = (long)(colors[0].red * 0xffffff); g = (long)(colors[0].green * 0xffffff); b = (long)(colors[0].blue * 0xffffff); /* render the first line */ for (i=1; i>16); *ptr++ = (unsigned char)(g>>16); *ptr++ = (unsigned char)(b>>16); r += dr; g += dg; b += db; k++; } r = (long)(colors[i].red * 0xffffff); g = (long)(colors[i].green * 0xffffff); b = (long)(colors[i].blue * 0xffffff); } for (j=k; j>16); *ptr++ = (unsigned char)(g>>16); *ptr++ = (unsigned char)(b>>16); } /* copy the first line to the other lines */ for (i=1; i 2, NULL); pixbuf = blank_pixbuf (width, height, FALSE); if (pixbuf == NULL) return NULL; pixels = gdk_pixbuf_get_pixels (pixbuf); rowstride = gdk_pixbuf_get_rowstride (pixbuf); ptr = pixels; if (count > height) count = height; if (count > 1) height2 = height/(count-1); else height2 = height; k = 0; r = (long)(colors[0].red * 0xffffff); g = (long)(colors[0].green * 0xffffff); b = (long)(colors[0].blue * 0xffffff); for (i=1; i>16); ptr[1] = (unsigned char)(g>>16); ptr[2] = (unsigned char)(b>>16); for (x=1; x <= width/2; x *= 2) memcpy (&(ptr[x*3]), ptr, x*3); memcpy (&(ptr[x*3]), ptr, (width - x)*3); ptr += rowstride; r += dr; g += dg; b += db; k++; } r = (long)(colors[i].red * 0xffffff); g = (long)(colors[i].green * 0xffffff); b = (long)(colors[i].blue * 0xffffff); } if (k>16); ptr[1] = (unsigned char) (g>>16); ptr[2] = (unsigned char) (b>>16); for (x=1; x <= width/2; x *= 2) memcpy (&(ptr[x*3]), ptr, x*3); memcpy (&(ptr[x*3]), ptr, (width - x)*3); ptr += rowstride; for (j=k+1; j 2, NULL); if (width == 1) return meta_gradient_create_multi_vertical (width, height, colors, count); else if (height == 1) return meta_gradient_create_multi_horizontal (width, height, colors, count); pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height); if (pixbuf == NULL) return NULL; pixels = gdk_pixbuf_get_pixels (pixbuf); rowstride = gdk_pixbuf_get_rowstride (pixbuf); if (count > width) count = width; if (count > height) count = height; if (count > 2) tmp = meta_gradient_create_multi_horizontal (2*width-1, 1, colors, count); else /* wrlib multiplies these colors by 256 before passing them in, but * I think it's a bug in wrlib, so changed here. I could be wrong * though, if we notice two-color multi diagonals not working. */ tmp = meta_gradient_create_horizontal (2*width-1, 1, &colors[0], &colors[1]); if (!tmp) { g_object_unref (G_OBJECT (pixbuf)); return NULL; } ptr = gdk_pixbuf_get_pixels (tmp); a = ((float)(width - 1))/((float)(height - 1)); width = width * 3; /* copy the first line to the other lines with corresponding offset */ for (j=0, offset=0; j 0); if (n_alphas == 1) { /* Optimize this */ simple_multiply_alpha (pixbuf, alphas[0]); return; } width = gdk_pixbuf_get_width (pixbuf); height = gdk_pixbuf_get_height (pixbuf); gradient = g_new (unsigned char, width); gradient_end = gradient + width; if (n_alphas > width) n_alphas = width; if (n_alphas > 1) width2 = width / (n_alphas - 1); else width2 = width; a = alphas[0] << 8; gradient_p = gradient; /* render the gradient into an array */ for (i = 1; i < n_alphas; i++) { da = (((int)(alphas[i] - (int) alphas[i-1])) << 8) / (int) width2; for (j = 0; j < width2; j++) { *gradient_p++ = (a >> 8); a += da; } a = alphas[i] << 8; } /* get leftover pixels */ while (gradient_p != gradient_end) { *gradient_p++ = a >> 8; } /* Now for each line of the pixbuf, fill in with the gradient */ pixels = gdk_pixbuf_get_pixels (pixbuf); rowstride = gdk_pixbuf_get_rowstride (pixbuf); p = pixels; i = 0; while (i < height) { unsigned char *row_end = p + rowstride; gradient_p = gradient; p += 3; while (gradient_p != gradient_end) { /* multiply the two alpha channels. not sure this is right. * but some end cases are that if the pixbuf contains 255, * then it should be modified to contain "alpha"; if the * pixbuf contains 0, it should remain 0. */ /* ((*p / 255.0) * (alpha / 255.0)) * 255; */ *p = (guchar) (((int) *p * (int) *gradient_p) / (int) 255); p += 4; ++gradient_p; } p = row_end; ++i; } g_free (gradient); } void meta_gradient_add_alpha (GdkPixbuf *pixbuf, const guchar *alphas, int n_alphas, MetaGradientType type) { g_return_if_fail (GDK_IS_PIXBUF (pixbuf)); g_return_if_fail (gdk_pixbuf_get_has_alpha (pixbuf)); g_return_if_fail (n_alphas > 0); switch (type) { case META_GRADIENT_HORIZONTAL: meta_gradient_add_alpha_horizontal (pixbuf, alphas, n_alphas); break; case META_GRADIENT_VERTICAL: g_printerr ("metacity: vertical alpha channel gradient not implemented yet\n"); break; case META_GRADIENT_DIAGONAL: g_printerr ("metacity: diagonal alpha channel gradient not implemented yet\n"); break; case META_GRADIENT_LAST: g_assert_not_reached (); break; } } muffin-2.8.4/src/ui/metaaccellabel.h0000664000175000017500000000670312623653707016251 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* Metacity hacked-up GtkAccelLabel */ /* Copyright (C) 2002 Red Hat, Inc. */ /* GTK - The GIMP Toolkit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * MetaAccelLabel: GtkLabel with accelerator monitoring facilities. * Copyright (C) 1998 Tim Janik * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. */ /* * Modified by the GTK+ Team and others 1997-2001. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ #ifndef __META_ACCEL_LABEL_H__ #define __META_ACCEL_LABEL_H__ #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #define META_TYPE_ACCEL_LABEL (meta_accel_label_get_type ()) #define META_ACCEL_LABEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_ACCEL_LABEL, MetaAccelLabel)) #define META_ACCEL_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_ACCEL_LABEL, MetaAccelLabelClass)) #define META_IS_ACCEL_LABEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_ACCEL_LABEL)) #define META_IS_ACCEL_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_ACCEL_LABEL)) #define META_ACCEL_LABEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_ACCEL_LABEL, MetaAccelLabelClass)) typedef struct _MetaAccelLabel MetaAccelLabel; typedef struct _MetaAccelLabelClass MetaAccelLabelClass; struct _MetaAccelLabel { GtkLabel label; MetaVirtualModifier accel_mods; guint accel_key; guint accel_padding; gchar *accel_string; guint16 accel_string_width; }; struct _MetaAccelLabelClass { GtkLabelClass parent_class; gchar *signal_quote1; gchar *signal_quote2; gchar *mod_name_shift; gchar *mod_name_control; gchar *mod_name_alt; gchar *mod_name_meta; gchar *mod_name_super; gchar *mod_name_hyper; gchar *mod_name_mod2; gchar *mod_name_mod3; gchar *mod_name_mod4; gchar *mod_name_mod5; gchar *mod_separator; gchar *accel_seperator; guint latin1_to_char : 1; /* Padding for future expansion */ void (*_gtk_reserved1) (void); void (*_gtk_reserved2) (void); void (*_gtk_reserved3) (void); void (*_gtk_reserved4) (void); }; GType meta_accel_label_get_type (void) G_GNUC_CONST; GtkWidget* meta_accel_label_new_with_mnemonic (const gchar *string); void meta_accel_label_set_accelerator (MetaAccelLabel *accel_label, guint accelerator_key, MetaVirtualModifier accelerator_mods); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __META_ACCEL_LABEL_H__ */ muffin-2.8.4/src/ui/theme-private.h0000664000175000017500000012315612623653707016107 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* Metacity Theme Rendering */ /* * Copyright (C) 2001 Havoc Pennington * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ #ifndef META_THEME_PRIVATE_H #define META_THEME_PRIVATE_H #include #include #include #include #include /** * MetaFrameStyle: (skip) * */ typedef struct _MetaFrameStyle MetaFrameStyle; /** * MetaFrameStyleSet: (skip) * */ typedef struct _MetaFrameStyleSet MetaFrameStyleSet; /** * MetaDrawOp: (skip) * */ typedef struct _MetaDrawOp MetaDrawOp; /** * MetaDrawOpList: (skip) * */ typedef struct _MetaDrawOpList MetaDrawOpList; /** * MetaGradientSpec: (skip) * */ typedef struct _MetaGradientSpec MetaGradientSpec; /** * MetaAlphaGradientSpec: (skip) * */ typedef struct _MetaAlphaGradientSpec MetaAlphaGradientSpec; /** * MetaColorSpec: (skip) * */ typedef struct _MetaColorSpec MetaColorSpec; /** * MetaFrameLayout: (skip) * */ typedef struct _MetaFrameLayout MetaFrameLayout; /** * MetaButtonSpace: (skip) * */ typedef struct _MetaButtonSpace MetaButtonSpace; /** * MetaFrameGeometry: (skip) * */ typedef struct _MetaFrameGeometry MetaFrameGeometry; /** * MetaPositionExprEnv: (skip) * */ typedef struct _MetaPositionExprEnv MetaPositionExprEnv; /** * MetaDrawInfo: (skip) * */ typedef struct _MetaDrawInfo MetaDrawInfo; #define META_THEME_ERROR (g_quark_from_static_string ("meta-theme-error")) typedef enum { META_THEME_ERROR_FRAME_GEOMETRY, META_THEME_ERROR_BAD_CHARACTER, META_THEME_ERROR_BAD_PARENS, META_THEME_ERROR_UNKNOWN_VARIABLE, META_THEME_ERROR_DIVIDE_BY_ZERO, META_THEME_ERROR_MOD_ON_FLOAT, META_THEME_ERROR_FAILED } MetaThemeError; /** * Whether a button's size is calculated from the area around it (aspect * sizing) or is given as a fixed height and width in pixels (fixed sizing). * * \bug This could be done away with; see the comment at the top of * MetaFrameLayout. */ typedef enum { META_BUTTON_SIZING_ASPECT, META_BUTTON_SIZING_FIXED, META_BUTTON_SIZING_LAST } MetaButtonSizing; /** * Various parameters used to calculate the geometry of a frame. * They are used inside a MetaFrameStyle. * This corresponds closely to the tag in a theme file. * * \bug button_sizing isn't really necessary, because we could easily say * that if button_aspect is zero, the height and width are fixed values. * This would also mean that MetaButtonSizing didn't need to exist, and * save code. **/ struct _MetaFrameLayout { /** Reference count. */ int refcount; /** Size of left side */ int left_width; /** Size of right side */ int right_width; /** Size of bottom side */ int bottom_height; /** Border of blue title region * \bug (blue?!) **/ GtkBorder title_border; /** Extra height for inside of title region, above the font height */ int title_vertical_pad; /** Right indent of buttons from edges of frame */ int right_titlebar_edge; /** Left indent of buttons from edges of frame */ int left_titlebar_edge; /** * Sizing rule of buttons, either META_BUTTON_SIZING_ASPECT * (in which case button_aspect will be honoured, and * button_width and button_height set from it), or * META_BUTTON_SIZING_FIXED (in which case we read the width * and height directly). */ MetaButtonSizing button_sizing; /** * Ratio of height/width. Honoured only if * button_sizing==META_BUTTON_SIZING_ASPECT. * Otherwise we figure out the height from the button_border. */ double button_aspect; /** Width of a button; set even when we are using aspect sizing */ int button_width; /** Height of a button; set even when we are using aspect sizing */ int button_height; /** Space around buttons */ GtkBorder button_border; /** scale factor for title text */ double title_scale; /** Whether title text will be displayed */ guint has_title : 1; /** Whether we should hide the buttons */ guint hide_buttons : 1; /** Radius of the top left-hand corner; 0 if not rounded */ guint top_left_corner_rounded_radius; /** Radius of the top right-hand corner; 0 if not rounded */ guint top_right_corner_rounded_radius; /** Radius of the bottom left-hand corner; 0 if not rounded */ guint bottom_left_corner_rounded_radius; /** Radius of the bottom right-hand corner; 0 if not rounded */ guint bottom_right_corner_rounded_radius; }; /** * The computed size of a button (really just a way of tying its * visible and clickable areas together). * The reason for two different rectangles here is Fitts' law & maximized * windows; see bug #97703 for more details. */ struct _MetaButtonSpace { /** The screen area where the button's image is drawn */ GdkRectangle visible; /** The screen area where the button can be activated by clicking */ GdkRectangle clickable; }; /** * Calculated actual geometry of the frame */ struct _MetaFrameGeometry { MetaFrameBorders borders; int width; int height; GdkRectangle title_rect; int left_titlebar_edge; int right_titlebar_edge; int top_titlebar_edge; int bottom_titlebar_edge; /* used for a memset hack */ #define ADDRESS_OF_BUTTON_RECTS(fgeom) (((char*)(fgeom)) + G_STRUCT_OFFSET (MetaFrameGeometry, close_rect)) #define LENGTH_OF_BUTTON_RECTS (G_STRUCT_OFFSET (MetaFrameGeometry, right_single_background) + sizeof (GdkRectangle) - G_STRUCT_OFFSET (MetaFrameGeometry, close_rect)) /* The button rects (if changed adjust memset hack) */ MetaButtonSpace close_rect; MetaButtonSpace max_rect; MetaButtonSpace min_rect; MetaButtonSpace menu_rect; MetaButtonSpace shade_rect; MetaButtonSpace above_rect; MetaButtonSpace stick_rect; MetaButtonSpace unshade_rect; MetaButtonSpace unabove_rect; MetaButtonSpace unstick_rect; #define MAX_MIDDLE_BACKGROUNDS (MAX_BUTTONS_PER_CORNER - 2) GdkRectangle left_left_background; GdkRectangle left_middle_backgrounds[MAX_MIDDLE_BACKGROUNDS]; GdkRectangle left_right_background; GdkRectangle left_single_background; GdkRectangle right_left_background; GdkRectangle right_middle_backgrounds[MAX_MIDDLE_BACKGROUNDS]; GdkRectangle right_right_background; GdkRectangle right_single_background; /* End of button rects (if changed adjust memset hack) */ /* Saved button layout */ MetaButtonLayout button_layout; int n_left_buttons; int n_right_buttons; /* Round corners */ guint top_left_corner_rounded_radius; guint top_right_corner_rounded_radius; guint bottom_left_corner_rounded_radius; guint bottom_right_corner_rounded_radius; }; typedef enum { META_IMAGE_FILL_SCALE, /* default, needs to be all-bits-zero for g_new0 */ META_IMAGE_FILL_TILE } MetaImageFillType; typedef enum { META_COLOR_SPEC_BASIC, META_COLOR_SPEC_GTK, META_COLOR_SPEC_GTK_CUSTOM, META_COLOR_SPEC_BLEND, META_COLOR_SPEC_SHADE } MetaColorSpecType; typedef enum { META_GTK_COLOR_FG, META_GTK_COLOR_BG, META_GTK_COLOR_LIGHT, META_GTK_COLOR_DARK, META_GTK_COLOR_MID, META_GTK_COLOR_TEXT, META_GTK_COLOR_BASE, META_GTK_COLOR_TEXT_AA, META_GTK_COLOR_LAST } MetaGtkColorComponent; struct _MetaColorSpec { MetaColorSpecType type; union { struct { GdkRGBA color; } basic; struct { MetaGtkColorComponent component; GtkStateFlags state; } gtk; struct { char *color_name; MetaColorSpec *fallback; } gtkcustom; struct { MetaColorSpec *foreground; MetaColorSpec *background; double alpha; GdkRGBA color; } blend; struct { MetaColorSpec *base; double factor; GdkRGBA color; } shade; } data; }; struct _MetaGradientSpec { MetaGradientType type; GSList *color_specs; }; struct _MetaAlphaGradientSpec { MetaGradientType type; unsigned char *alphas; int n_alphas; }; struct _MetaDrawInfo { GdkPixbuf *mini_icon; GdkPixbuf *icon; PangoLayout *title_layout; int title_layout_width; int title_layout_height; const MetaFrameGeometry *fgeom; }; /** * A drawing operation in our simple vector drawing language. */ typedef enum { /** Basic drawing-- line */ META_DRAW_LINE, /** Basic drawing-- rectangle */ META_DRAW_RECTANGLE, /** Basic drawing-- arc */ META_DRAW_ARC, /** Clip to a rectangle */ META_DRAW_CLIP, /* Texture thingies */ /** Just a filled rectangle with alpha */ META_DRAW_TINT, META_DRAW_GRADIENT, META_DRAW_IMAGE, /** GTK theme engine stuff */ META_DRAW_GTK_ARROW, META_DRAW_GTK_BOX, META_DRAW_GTK_VLINE, /** App's window icon */ META_DRAW_ICON, /** App's window title */ META_DRAW_TITLE, /** a draw op list */ META_DRAW_OP_LIST, /** tiled draw op list */ META_DRAW_TILE } MetaDrawType; typedef enum { POS_TOKEN_INT, POS_TOKEN_DOUBLE, POS_TOKEN_OPERATOR, POS_TOKEN_VARIABLE, POS_TOKEN_OPEN_PAREN, POS_TOKEN_CLOSE_PAREN } PosTokenType; typedef enum { POS_OP_NONE, POS_OP_ADD, POS_OP_SUBTRACT, POS_OP_MULTIPLY, POS_OP_DIVIDE, POS_OP_MOD, POS_OP_MAX, POS_OP_MIN } PosOperatorType; /** * A token, as output by the tokeniser. * * \ingroup tokenizer */ typedef struct { PosTokenType type; union { struct { int val; } i; struct { double val; } d; struct { PosOperatorType op; } o; struct { char *name; GQuark name_quark; } v; } d; } PosToken; /** * MetaDrawSpec: (skip) * * A computed expression in our simple vector drawing language. * While it appears to take the form of a tree, this is actually * merely a list; concerns such as precedence of operators are * currently recomputed on every recalculation. * * Created by meta_draw_spec_new(), destroyed by meta_draw_spec_free(). * pos_eval() fills this with ...FIXME. Are tokens a tree or a list? * \ingroup parser */ typedef struct _MetaDrawSpec MetaDrawSpec; struct _MetaDrawSpec { /** * If this spec is constant, this is the value of the constant; * otherwise it is zero. */ int value; /** A list of tokens in the expression. */ PosToken *tokens; /** How many tokens are in the tokens list. */ int n_tokens; /** Does the expression contain any variables? */ gboolean constant : 1; }; /** * A single drawing operation in our simple vector drawing language. */ struct _MetaDrawOp { MetaDrawType type; /* Positions are strings because they can be expressions */ union { struct { MetaColorSpec *color_spec; int dash_on_length; int dash_off_length; int width; MetaDrawSpec *x1; MetaDrawSpec *y1; MetaDrawSpec *x2; MetaDrawSpec *y2; } line; struct { MetaColorSpec *color_spec; gboolean filled; MetaDrawSpec *x; MetaDrawSpec *y; MetaDrawSpec *width; MetaDrawSpec *height; } rectangle; struct { MetaColorSpec *color_spec; gboolean filled; MetaDrawSpec *x; MetaDrawSpec *y; MetaDrawSpec *width; MetaDrawSpec *height; double start_angle; double extent_angle; } arc; struct { MetaDrawSpec *x; MetaDrawSpec *y; MetaDrawSpec *width; MetaDrawSpec *height; } clip; struct { MetaColorSpec *color_spec; MetaAlphaGradientSpec *alpha_spec; MetaDrawSpec *x; MetaDrawSpec *y; MetaDrawSpec *width; MetaDrawSpec *height; } tint; struct { MetaGradientSpec *gradient_spec; MetaAlphaGradientSpec *alpha_spec; MetaDrawSpec *x; MetaDrawSpec *y; MetaDrawSpec *width; MetaDrawSpec *height; } gradient; struct { MetaColorSpec *colorize_spec; MetaAlphaGradientSpec *alpha_spec; GdkPixbuf *pixbuf; MetaDrawSpec *x; MetaDrawSpec *y; MetaDrawSpec *width; MetaDrawSpec *height; guint32 colorize_cache_pixel; GdkPixbuf *colorize_cache_pixbuf; MetaImageFillType fill_type; unsigned int vertical_stripes : 1; unsigned int horizontal_stripes : 1; } image; struct { GtkStateFlags state; GtkShadowType shadow; GtkArrowType arrow; gboolean filled; MetaDrawSpec *x; MetaDrawSpec *y; MetaDrawSpec *width; MetaDrawSpec *height; } gtk_arrow; struct { GtkStateFlags state; GtkShadowType shadow; MetaDrawSpec *x; MetaDrawSpec *y; MetaDrawSpec *width; MetaDrawSpec *height; } gtk_box; struct { GtkStateFlags state; MetaDrawSpec *x; MetaDrawSpec *y1; MetaDrawSpec *y2; } gtk_vline; struct { MetaAlphaGradientSpec *alpha_spec; MetaDrawSpec *x; MetaDrawSpec *y; MetaDrawSpec *width; MetaDrawSpec *height; MetaImageFillType fill_type; } icon; struct { MetaColorSpec *color_spec; MetaDrawSpec *x; MetaDrawSpec *y; MetaDrawSpec *ellipsize_width; } title; struct { MetaDrawOpList *op_list; MetaDrawSpec *x; MetaDrawSpec *y; MetaDrawSpec *width; MetaDrawSpec *height; } op_list; struct { MetaDrawOpList *op_list; MetaDrawSpec *x; MetaDrawSpec *y; MetaDrawSpec *width; MetaDrawSpec *height; MetaDrawSpec *tile_xoffset; MetaDrawSpec *tile_yoffset; MetaDrawSpec *tile_width; MetaDrawSpec *tile_height; } tile; } data; }; /** * A list of MetaDrawOp objects. Maintains a reference count. * Grows as necessary and allows the allocation of unused spaces * to keep reallocations to a minimum. * * \bug Do we really win anything from not using the equivalent * GLib structures? */ struct _MetaDrawOpList { int refcount; MetaDrawOp **ops; int n_ops; int n_allocated; }; typedef enum { META_BUTTON_STATE_NORMAL, META_BUTTON_STATE_PRESSED, META_BUTTON_STATE_PRELIGHT, META_BUTTON_STATE_LAST } MetaButtonState; typedef enum { /* Ordered so that background is drawn first */ META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND, META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND, META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND, META_BUTTON_TYPE_LEFT_SINGLE_BACKGROUND, META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND, META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND, META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND, META_BUTTON_TYPE_RIGHT_SINGLE_BACKGROUND, META_BUTTON_TYPE_CLOSE, META_BUTTON_TYPE_MAXIMIZE, META_BUTTON_TYPE_MINIMIZE, META_BUTTON_TYPE_MENU, META_BUTTON_TYPE_SHADE, META_BUTTON_TYPE_ABOVE, META_BUTTON_TYPE_STICK, META_BUTTON_TYPE_UNSHADE, META_BUTTON_TYPE_UNABOVE, META_BUTTON_TYPE_UNSTICK, META_BUTTON_TYPE_LAST } MetaButtonType; typedef enum { META_MENU_ICON_TYPE_CLOSE, META_MENU_ICON_TYPE_MAXIMIZE, META_MENU_ICON_TYPE_UNMAXIMIZE, META_MENU_ICON_TYPE_MINIMIZE, META_MENU_ICON_TYPE_LAST } MetaMenuIconType; typedef enum { /* Listed in the order in which the textures are drawn. * (though this only matters for overlaps of course.) * Buttons are drawn after the frame textures. * * On the corners, horizontal pieces are arbitrarily given the * corner area: * * ===== |==== * | | * | rather than | * */ /* entire frame */ META_FRAME_PIECE_ENTIRE_BACKGROUND, /* entire titlebar background */ META_FRAME_PIECE_TITLEBAR, /* portion of the titlebar background inside the titlebar * background edges */ META_FRAME_PIECE_TITLEBAR_MIDDLE, /* left end of titlebar */ META_FRAME_PIECE_LEFT_TITLEBAR_EDGE, /* right end of titlebar */ META_FRAME_PIECE_RIGHT_TITLEBAR_EDGE, /* top edge of titlebar */ META_FRAME_PIECE_TOP_TITLEBAR_EDGE, /* bottom edge of titlebar */ META_FRAME_PIECE_BOTTOM_TITLEBAR_EDGE, /* render over title background (text area) */ META_FRAME_PIECE_TITLE, /* left edge of the frame */ META_FRAME_PIECE_LEFT_EDGE, /* right edge of the frame */ META_FRAME_PIECE_RIGHT_EDGE, /* bottom edge of the frame */ META_FRAME_PIECE_BOTTOM_EDGE, /* place over entire frame, after drawing everything else */ META_FRAME_PIECE_OVERLAY, /* Used to get size of the enum */ META_FRAME_PIECE_LAST } MetaFramePiece; /** * How to draw a frame in a particular state (say, a focussed, non-maximised, * resizable frame). This corresponds closely to the tag * in a theme file. */ struct _MetaFrameStyle { /** Reference count. */ int refcount; /** * Parent style. * Settings which are unspecified here will be taken from there. */ MetaFrameStyle *parent; /** Operations for drawing each kind of button in each state. */ MetaDrawOpList *buttons[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST]; /** Operations for drawing each piece of the frame. */ MetaDrawOpList *pieces[META_FRAME_PIECE_LAST]; /** * Details such as the height and width of each edge, the corner rounding, * and the aspect ratio of the buttons. */ MetaFrameLayout *layout; /** * Background colour of the window. Only present in theme formats * 2 and above. Can be NULL to use the standard GTK theme engine. */ MetaColorSpec *window_background_color; /** * Transparency of the window background. 0=transparent; 255=opaque. */ guint8 window_background_alpha; }; /* Kinds of frame... * * normal -> noresize / vert only / horz only / both * focused / unfocused * max -> focused / unfocused * shaded -> focused / unfocused * max/shaded -> focused / unfocused * * so 4 states with 8 sub-states in one, 2 sub-states in the other 3, * meaning 14 total * * 14 window states times 7 or 8 window types. Except some * window types never get a frame so that narrows it down a bit. * */ typedef enum { META_FRAME_STATE_NORMAL, META_FRAME_STATE_MAXIMIZED, META_FRAME_STATE_TILED_LEFT, META_FRAME_STATE_TILED_RIGHT, META_FRAME_STATE_SHADED, META_FRAME_STATE_MAXIMIZED_AND_SHADED, META_FRAME_STATE_TILED_LEFT_AND_SHADED, META_FRAME_STATE_TILED_RIGHT_AND_SHADED, META_FRAME_STATE_LAST } MetaFrameState; typedef enum { META_FRAME_RESIZE_NONE, META_FRAME_RESIZE_VERTICAL, META_FRAME_RESIZE_HORIZONTAL, META_FRAME_RESIZE_BOTH, META_FRAME_RESIZE_LAST } MetaFrameResize; typedef enum { META_FRAME_FOCUS_NO, META_FRAME_FOCUS_YES, META_FRAME_FOCUS_LAST } MetaFrameFocus; /** * How to draw frames at different times: when it's maximised or not, shaded * or not, when it's focussed or not, and (for non-maximised windows), when * it can be horizontally or vertically resized, both, or neither. * Not all window types actually get a frame. * * A theme contains one of these objects for each type of window (each * MetaFrameType), that is, normal, dialogue (modal and non-modal), etc. * * This corresponds closely to the tag in a theme file. */ struct _MetaFrameStyleSet { int refcount; MetaFrameStyleSet *parent; MetaFrameStyle *normal_styles[META_FRAME_RESIZE_LAST][META_FRAME_FOCUS_LAST]; MetaFrameStyle *maximized_styles[META_FRAME_FOCUS_LAST]; MetaFrameStyle *tiled_left_styles[META_FRAME_FOCUS_LAST]; MetaFrameStyle *tiled_right_styles[META_FRAME_FOCUS_LAST]; MetaFrameStyle *tiled_ulc_styles[META_FRAME_FOCUS_LAST]; MetaFrameStyle *tiled_llc_styles[META_FRAME_FOCUS_LAST]; MetaFrameStyle *tiled_urc_styles[META_FRAME_FOCUS_LAST]; MetaFrameStyle *tiled_lrc_styles[META_FRAME_FOCUS_LAST]; MetaFrameStyle *shaded_styles[META_FRAME_RESIZE_LAST][META_FRAME_FOCUS_LAST]; MetaFrameStyle *maximized_and_shaded_styles[META_FRAME_FOCUS_LAST]; MetaFrameStyle *tiled_left_and_shaded_styles[META_FRAME_FOCUS_LAST]; MetaFrameStyle *tiled_right_and_shaded_styles[META_FRAME_FOCUS_LAST]; MetaFrameStyle *tiled_ulc_and_shaded_styles[META_FRAME_FOCUS_LAST]; MetaFrameStyle *tiled_llc_and_shaded_styles[META_FRAME_FOCUS_LAST]; MetaFrameStyle *tiled_urc_and_shaded_styles[META_FRAME_FOCUS_LAST]; MetaFrameStyle *tiled_lrc_and_shaded_styles[META_FRAME_FOCUS_LAST]; }; /** * A theme. This is a singleton class which groups all settings from a theme * on disk together. * * \bug It is rather useless to keep the metadata fields in core, I think. */ struct _MetaTheme { /** Name of the theme (on disk), e.g. "Crux" */ char *name; /** Path to the files associated with the theme */ char *dirname; /** * Filename of the XML theme file. * \bug Kept lying around for no discernable reason. */ char *filename; /** Metadata: Human-readable name of the theme. */ char *readable_name; /** Metadata: Author of the theme. */ char *author; /** Metadata: Copyright holder. */ char *copyright; /** Metadata: Date of the theme. */ char *date; /** Metadata: Description of the theme. */ char *description; /** Version of the theme format. Older versions cannot use the features * of newer versions even if they think they can (this is to allow forward * and backward compatibility. */ guint format_version; guint scale; /** Symbol table of integer constants. */ GHashTable *integer_constants; /** Symbol table of float constants. */ GHashTable *float_constants; /** * Symbol table of colour constants (hex triples, and triples * plus alpha). * */ GHashTable *color_constants; GHashTable *images_by_filename; GHashTable *layouts_by_name; GHashTable *draw_op_lists_by_name; GHashTable *styles_by_name; GHashTable *style_sets_by_name; MetaFrameStyleSet *style_sets_by_type[META_FRAME_TYPE_LAST]; GQuark quark_width; GQuark quark_height; GQuark quark_object_width; GQuark quark_object_height; GQuark quark_left_width; GQuark quark_right_width; GQuark quark_top_height; GQuark quark_bottom_height; GQuark quark_mini_icon_width; GQuark quark_mini_icon_height; GQuark quark_icon_width; GQuark quark_icon_height; GQuark quark_title_width; GQuark quark_title_height; GQuark quark_frame_x_center; GQuark quark_frame_y_center; }; struct _MetaPositionExprEnv { MetaRectangle rect; /* size of an object being drawn, if it has a natural size */ int object_width; int object_height; /* global object sizes, always available */ int left_width; int right_width; int top_height; int bottom_height; int title_width; int title_height; int frame_x_center; int frame_y_center; int mini_icon_width; int mini_icon_height; int icon_width; int icon_height; /* Theme so we can look up constants */ MetaTheme *theme; }; MetaFrameLayout* meta_frame_layout_new (void); MetaFrameLayout* meta_frame_layout_copy (const MetaFrameLayout *src); void meta_frame_layout_ref (MetaFrameLayout *layout); void meta_frame_layout_unref (MetaFrameLayout *layout); void meta_frame_layout_get_borders (const MetaFrameLayout *layout, int text_height, MetaFrameFlags flags, MetaFrameType type, MetaFrameBorders *borders); void meta_frame_layout_calc_geometry (const MetaFrameLayout *layout, int text_height, MetaFrameFlags flags, int client_width, int client_height, const MetaButtonLayout *button_layout, MetaFrameType type, MetaFrameGeometry *fgeom, MetaTheme *theme); gboolean meta_frame_layout_validate (const MetaFrameLayout *layout, GError **error); gboolean meta_parse_position_expression (MetaDrawSpec *spec, const MetaPositionExprEnv *env, int *x_return, int *y_return, GError **err); gboolean meta_parse_size_expression (MetaDrawSpec *spec, const MetaPositionExprEnv *env, int *val_return, GError **err); MetaDrawSpec* meta_draw_spec_new (MetaTheme *theme, const char *expr, GError **error); void meta_draw_spec_free (MetaDrawSpec *spec); MetaColorSpec* meta_color_spec_new (MetaColorSpecType type); MetaColorSpec* meta_color_spec_new_from_string (const char *str, GError **err); MetaColorSpec* meta_color_spec_new_gtk (MetaGtkColorComponent component, GtkStateFlags state); void meta_color_spec_free (MetaColorSpec *spec); void meta_color_spec_render (MetaColorSpec *spec, GtkStyleContext *style_gtk, GdkRGBA *color); MetaDrawOp* meta_draw_op_new (MetaDrawType type); void meta_draw_op_free (MetaDrawOp *op); void meta_draw_op_draw (const MetaDrawOp *op, GtkWidget *widget, cairo_t *cr, const MetaDrawInfo *info, /* logical region being drawn */ MetaRectangle logical_region); void meta_draw_op_draw_with_style (const MetaDrawOp *op, GtkStyleContext *style_gtk, GtkWidget *widget, cairo_t *cr, const MetaDrawInfo *info, /* logical region being drawn */ MetaRectangle logical_region); MetaDrawOpList* meta_draw_op_list_new (int n_preallocs); void meta_draw_op_list_ref (MetaDrawOpList *op_list); void meta_draw_op_list_unref (MetaDrawOpList *op_list); void meta_draw_op_list_draw (const MetaDrawOpList *op_list, GtkWidget *widget, cairo_t *cr, const MetaDrawInfo *info, MetaRectangle rect); void meta_draw_op_list_draw_with_style (const MetaDrawOpList *op_list, GtkStyleContext *style_gtk, GtkWidget *widget, cairo_t *cr, const MetaDrawInfo *info, MetaRectangle rect); void meta_draw_op_list_append (MetaDrawOpList *op_list, MetaDrawOp *op); gboolean meta_draw_op_list_validate (MetaDrawOpList *op_list, GError **error); gboolean meta_draw_op_list_contains (MetaDrawOpList *op_list, MetaDrawOpList *child); MetaGradientSpec* meta_gradient_spec_new (MetaGradientType type); void meta_gradient_spec_free (MetaGradientSpec *desc); GdkPixbuf* meta_gradient_spec_render (const MetaGradientSpec *desc, GtkStyleContext *gtk_style, int width, int height); gboolean meta_gradient_spec_validate (MetaGradientSpec *spec, GError **error); MetaAlphaGradientSpec* meta_alpha_gradient_spec_new (MetaGradientType type, int n_alphas); void meta_alpha_gradient_spec_free (MetaAlphaGradientSpec *spec); MetaFrameStyle* meta_frame_style_new (MetaFrameStyle *parent); void meta_frame_style_ref (MetaFrameStyle *style); void meta_frame_style_unref (MetaFrameStyle *style); void meta_frame_style_draw (MetaFrameStyle *style, GtkWidget *widget, cairo_t *cr, const MetaFrameGeometry *fgeom, int client_width, int client_height, PangoLayout *title_layout, int text_height, MetaButtonState button_states[META_BUTTON_TYPE_LAST], GdkPixbuf *mini_icon, GdkPixbuf *icon); void meta_frame_style_draw_with_style (MetaFrameStyle *style, GtkStyleContext *style_gtk, GtkWidget *widget, cairo_t *cr, const MetaFrameGeometry *fgeom, int client_width, int client_height, PangoLayout *title_layout, int text_height, MetaButtonState button_states[META_BUTTON_TYPE_LAST], GdkPixbuf *mini_icon, GdkPixbuf *icon); gboolean meta_frame_style_validate (MetaFrameStyle *style, guint current_theme_version, GError **error); MetaFrameStyleSet* meta_frame_style_set_new (MetaFrameStyleSet *parent); void meta_frame_style_set_ref (MetaFrameStyleSet *style_set); void meta_frame_style_set_unref (MetaFrameStyleSet *style_set); gboolean meta_frame_style_set_validate (MetaFrameStyleSet *style_set, GError **error); GdkPixbuf* meta_theme_load_image (MetaTheme *theme, const char *filename, guint size_of_theme_icons, GError **error); MetaFrameStyle* meta_theme_get_frame_style (MetaTheme *theme, MetaFrameType type, MetaFrameFlags flags); double meta_theme_get_title_scale (MetaTheme *theme, MetaFrameType type, MetaFrameFlags flags); void meta_theme_draw_frame (MetaTheme *theme, GtkWidget *widget, cairo_t *cr, MetaFrameType type, MetaFrameFlags flags, int client_width, int client_height, PangoLayout *title_layout, int text_height, const MetaButtonLayout *button_layout, MetaButtonState button_states[META_BUTTON_TYPE_LAST], GdkPixbuf *mini_icon, GdkPixbuf *icon); void meta_theme_draw_frame_with_style (MetaTheme *theme, GtkStyleContext *style_gtk, GtkWidget *widget, cairo_t *cr, MetaFrameType type, MetaFrameFlags flags, int client_width, int client_height, PangoLayout *title_layout, int text_height, const MetaButtonLayout *button_layout, MetaButtonState button_states[META_BUTTON_TYPE_LAST], GdkPixbuf *mini_icon, GdkPixbuf *icon); void meta_theme_get_frame_borders (MetaTheme *theme, MetaFrameType type, int text_height, MetaFrameFlags flags, MetaFrameBorders *borders); void meta_theme_calc_geometry (MetaTheme *theme, MetaFrameType type, int text_height, MetaFrameFlags flags, int client_width, int client_height, const MetaButtonLayout *button_layout, MetaFrameGeometry *fgeom); MetaFrameLayout* meta_theme_lookup_layout (MetaTheme *theme, const char *name); void meta_theme_insert_layout (MetaTheme *theme, const char *name, MetaFrameLayout *layout); MetaDrawOpList* meta_theme_lookup_draw_op_list (MetaTheme *theme, const char *name); void meta_theme_insert_draw_op_list (MetaTheme *theme, const char *name, MetaDrawOpList *op_list); MetaFrameStyle* meta_theme_lookup_style (MetaTheme *theme, const char *name); void meta_theme_insert_style (MetaTheme *theme, const char *name, MetaFrameStyle *style); MetaFrameStyleSet* meta_theme_lookup_style_set (MetaTheme *theme, const char *name); void meta_theme_insert_style_set (MetaTheme *theme, const char *name, MetaFrameStyleSet *style_set); gboolean meta_theme_define_int_constant (MetaTheme *theme, const char *name, int value, GError **error); gboolean meta_theme_lookup_int_constant (MetaTheme *theme, const char *name, int *value); gboolean meta_theme_define_float_constant (MetaTheme *theme, const char *name, double value, GError **error); gboolean meta_theme_lookup_float_constant (MetaTheme *theme, const char *name, double *value); gboolean meta_theme_define_color_constant (MetaTheme *theme, const char *name, const char *value, GError **error); gboolean meta_theme_lookup_color_constant (MetaTheme *theme, const char *name, char **value); gboolean meta_theme_replace_constants (MetaTheme *theme, PosToken *tokens, int n_tokens, GError **err); /* random stuff */ PangoFontDescription* meta_gtk_widget_get_font_desc (GtkWidget *widget, double scale, const PangoFontDescription *override); int meta_pango_font_desc_get_text_height (const PangoFontDescription *font_desc, PangoContext *context); /* Enum converters */ MetaGtkColorComponent meta_color_component_from_string (const char *str); const char* meta_color_component_to_string (MetaGtkColorComponent component); MetaButtonState meta_button_state_from_string (const char *str); const char* meta_button_state_to_string (MetaButtonState state); MetaButtonType meta_button_type_from_string (const char *str, MetaTheme *theme); const char* meta_button_type_to_string (MetaButtonType type); MetaFramePiece meta_frame_piece_from_string (const char *str); const char* meta_frame_piece_to_string (MetaFramePiece piece); MetaFrameState meta_frame_state_from_string (const char *str); const char* meta_frame_state_to_string (MetaFrameState state); MetaFrameResize meta_frame_resize_from_string (const char *str); const char* meta_frame_resize_to_string (MetaFrameResize resize); MetaFrameFocus meta_frame_focus_from_string (const char *str); const char* meta_frame_focus_to_string (MetaFrameFocus focus); MetaFrameType meta_frame_type_from_string (const char *str); MetaGradientType meta_gradient_type_from_string (const char *str); const char* meta_gradient_type_to_string (MetaGradientType type); GtkStateFlags meta_gtk_state_from_string (const char *str); const char* meta_gtk_state_to_string (GtkStateFlags state); GtkShadowType meta_gtk_shadow_from_string (const char *str); const char* meta_gtk_shadow_to_string (GtkShadowType shadow); GtkArrowType meta_gtk_arrow_from_string (const char *str); const char* meta_gtk_arrow_to_string (GtkArrowType arrow); MetaImageFillType meta_image_fill_type_from_string (const char *str); const char* meta_image_fill_type_to_string (MetaImageFillType fill_type); void meta_gtk_style_get_light_color (GtkStyleContext *style, GtkStateFlags state, GdkRGBA *color); void meta_gtk_style_get_dark_color (GtkStyleContext *style, GtkStateFlags state, GdkRGBA *color); guint meta_theme_earliest_version_with_button (MetaButtonType type); #define META_THEME_ALLOWS(theme, feature) (theme->format_version >= feature) /* What version of the theme file format were various features introduced in? */ #define META_THEME_SHADE_STICK_ABOVE_BUTTONS 2 #define META_THEME_UBIQUITOUS_CONSTANTS 2 #define META_THEME_VARIED_ROUND_CORNERS 2 #define META_THEME_IMAGES_FROM_ICON_THEMES 2 #define META_THEME_UNRESIZABLE_SHADED_STYLES 2 #define META_THEME_DEGREES_IN_ARCS 2 #define META_THEME_HIDDEN_BUTTONS 2 #define META_THEME_COLOR_CONSTANTS 2 #define META_THEME_FRAME_BACKGROUNDS 2 #endif /* META_THEME_PRIVATE_H */ muffin-2.8.4/src/ui/theme.c0000664000175000017500000063317012623653707014434 0ustar fabiofabio/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* Metacity Theme Rendering */ /* * Copyright (C) 2001 Havoc Pennington * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA * 02110-1335, USA. */ /** * SECTION:theme * @short_description: Making Metacity look pretty * * The window decorations drawn by Metacity are described by files on disk * known internally as "themes" (externally as "window border themes" on * http://art.gnome.org/themes/metacity/ or "Metacity themes"). This file * contains most of the code necessary to support themes; it does not * contain the XML parser, which is in theme-parser.c. * * \bug This is a big file with lots of different subsystems, which might * be better split out into separate files. */ /* * \defgroup tokenizer The theme expression tokenizer * * Themes can use a simple expression language to represent the values of * things. This is the tokeniser used for that language. * * \bug We could remove almost all this code by using GScanner instead, * but we would also have to find every expression in every existing theme * we could and make sure the parse trees were the same. */ /* * \defgroup parser The theme expression parser * * Themes can use a simple expression language to represent the values of * things. This is the parser used for that language. */ #include #include "theme-private.h" #include #include #include #include #include #include #include #define GDK_COLOR_RGBA(color) \ ((guint32) (0xff | \ ((int)((color).red * 255) << 24) | \ ((int)((color).green * 255) << 16) | \ ((int)((color).blue * 255) << 8))) #define GDK_COLOR_RGB(color) \ ((guint32) (((int)((color).red * 255) << 16) | \ ((int)((color).green * 255) << 8) | \ ((int)((color).blue * 255)))) #define ALPHA_TO_UCHAR(d) ((unsigned char) ((d) * 255)) #define DEBUG_FILL_STRUCT(s) memset ((s), 0xef, sizeof (*(s))) #define CLAMP_UCHAR(v) ((guchar) (CLAMP (((int)v), (int)0, (int)255))) #define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11) static void gtk_style_shade (GdkRGBA *a, GdkRGBA *b, gdouble k); static void rgb_to_hls (gdouble *r, gdouble *g, gdouble *b); static void hls_to_rgb (gdouble *h, gdouble *l, gdouble *s); /* * The current theme. (Themes are singleton.) */ static MetaTheme *meta_current_theme = NULL; static GdkPixbuf * colorize_pixbuf (GdkPixbuf *orig, GdkRGBA *new_color) { GdkPixbuf *pixbuf; double intensity; int x, y; const guchar *src; guchar *dest; int orig_rowstride; int dest_rowstride; int width, height; gboolean has_alpha; const guchar *src_pixels; guchar *dest_pixels; pixbuf = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (orig), gdk_pixbuf_get_has_alpha (orig), gdk_pixbuf_get_bits_per_sample (orig), gdk_pixbuf_get_width (orig), gdk_pixbuf_get_height (orig)); if (pixbuf == NULL) return NULL; orig_rowstride = gdk_pixbuf_get_rowstride (orig); dest_rowstride = gdk_pixbuf_get_rowstride (pixbuf); width = gdk_pixbuf_get_width (pixbuf); height = gdk_pixbuf_get_height (pixbuf); has_alpha = gdk_pixbuf_get_has_alpha (orig); src_pixels = gdk_pixbuf_get_pixels (orig); dest_pixels = gdk_pixbuf_get_pixels (pixbuf); for (y = 0; y < height; y++) { src = src_pixels + y * orig_rowstride; dest = dest_pixels + y * dest_rowstride; for (x = 0; x < width; x++) { double dr, dg, db; intensity = INTENSITY (src[0], src[1], src[2]) / 255.0; if (intensity <= 0.5) { /* Go from black at intensity = 0.0 to new_color at intensity = 0.5 */ dr = new_color->red * intensity * 2.0; dg = new_color->green * intensity * 2.0; db = new_color->blue * intensity * 2.0; } else { /* Go from new_color at intensity = 0.5 to white at intensity = 1.0 */ dr = new_color->red + (1.0 - new_color->red) * (intensity - 0.5) * 2.0; dg = new_color->green + (1.0 - new_color->green) * (intensity - 0.5) * 2.0; db = new_color->blue + (1.0 - new_color->blue) * (intensity - 0.5) * 2.0; } dest[0] = CLAMP_UCHAR (255 * dr); dest[1] = CLAMP_UCHAR (255 * dg); dest[2] = CLAMP_UCHAR (255 * db); if (has_alpha) { dest[3] = src[3]; src += 4; dest += 4; } else { src += 3; dest += 3; } } } return pixbuf; } static void color_composite (const GdkRGBA *bg, const GdkRGBA *fg, double alpha, GdkRGBA *color) { *color = *bg; color->red = color->red + (fg->red - color->red) * alpha; color->green = color->green + (fg->green - color->green) * alpha; color->blue = color->blue + (fg->blue - color->blue) * alpha; } /* * Sets all the fields of a border to dummy values. * * \param border The border whose fields should be reset. */ static void init_border (GtkBorder *border) { border->top = -1; border->bottom = -1; border->left = -1; border->right = -1; } /** * meta_frame_layout_new: (skip) * * Creates a new, empty MetaFrameLayout. The fields will be set to dummy * values. * * Returns: The newly created MetaFrameLayout. */ LOCAL_SYMBOL MetaFrameLayout* meta_frame_layout_new (void) { MetaFrameLayout *layout; layout = g_new0 (MetaFrameLayout, 1); layout->refcount = 1; /* Fill with -1 values to detect invalid themes */ layout->left_width = -1; layout->right_width = -1; layout->bottom_height = -1; init_border (&layout->title_border); layout->title_vertical_pad = -1; layout->right_titlebar_edge = -1; layout->left_titlebar_edge = -1; layout->button_sizing = META_BUTTON_SIZING_LAST; layout->button_aspect = 1.0; layout->button_width = -1; layout->button_height = -1; layout->has_title = TRUE; layout->title_scale = 1.0; init_border (&layout->button_border); return layout; } /* * */ static gboolean validate_border (const GtkBorder *border, const char **bad) { *bad = NULL; if (border->top < 0) *bad = _("top"); else if (border->bottom < 0) *bad = _("bottom"); else if (border->left < 0) *bad = _("left"); else if (border->right < 0) *bad = _("right"); return *bad == NULL; } /* * Ensures that the theme supplied a particular dimension. When a * MetaFrameLayout is created, all its integer fields are set to -1 * by meta_frame_layout_new(). After an instance of this type * should have been initialised, this function checks that * a given field is not still at -1. It is never called directly, but * rather via the CHECK_GEOMETRY_VALUE and CHECK_GEOMETRY_BORDER * macros. * * \param val The value to check * \param name The name to use in the error message * \param[out] error Set to an error if val was not initialised */ static gboolean validate_geometry_value (int val, const char *name, GError **error) { if (val < 0) { g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FRAME_GEOMETRY, _("frame geometry does not specify \"%s\" dimension"), name); return FALSE; } else return TRUE; } static gboolean validate_geometry_border (const GtkBorder *border, const char *name, GError **error) { const char *bad; if (!validate_border (border, &bad)) { g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FRAME_GEOMETRY, _("frame geometry does not specify dimension \"%s\" for border \"%s\""), bad, name); return FALSE; } else return TRUE; } LOCAL_SYMBOL gboolean meta_frame_layout_validate (const MetaFrameLayout *layout, GError **error) { g_return_val_if_fail (layout != NULL, FALSE); #define CHECK_GEOMETRY_VALUE(vname) if (!validate_geometry_value (layout->vname, #vname, error)) return FALSE #define CHECK_GEOMETRY_BORDER(bname) if (!validate_geometry_border (&layout->bname, #bname, error)) return FALSE CHECK_GEOMETRY_VALUE (left_width); CHECK_GEOMETRY_VALUE (right_width); CHECK_GEOMETRY_VALUE (bottom_height); CHECK_GEOMETRY_BORDER (title_border); CHECK_GEOMETRY_VALUE (title_vertical_pad); CHECK_GEOMETRY_VALUE (right_titlebar_edge); CHECK_GEOMETRY_VALUE (left_titlebar_edge); switch (layout->button_sizing) { case META_BUTTON_SIZING_ASPECT: if (layout->button_aspect < (0.1) || layout->button_aspect > (15.0)) { g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FRAME_GEOMETRY, _("Button aspect ratio %g is not reasonable"), layout->button_aspect); return FALSE; } break; case META_BUTTON_SIZING_FIXED: CHECK_GEOMETRY_VALUE (button_width); CHECK_GEOMETRY_VALUE (button_height); break; case META_BUTTON_SIZING_LAST: g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FRAME_GEOMETRY, _("Frame geometry does not specify size of buttons")); return FALSE; } CHECK_GEOMETRY_BORDER (button_border); return TRUE; } LOCAL_SYMBOL MetaFrameLayout* meta_frame_layout_copy (const MetaFrameLayout *src) { MetaFrameLayout *layout; layout = g_new0 (MetaFrameLayout, 1); *layout = *src; layout->refcount = 1; return layout; } LOCAL_SYMBOL void meta_frame_layout_ref (MetaFrameLayout *layout) { g_return_if_fail (layout != NULL); layout->refcount += 1; } LOCAL_SYMBOL void meta_frame_layout_unref (MetaFrameLayout *layout) { g_return_if_fail (layout != NULL); g_return_if_fail (layout->refcount > 0); layout->refcount -= 1; if (layout->refcount == 0) { DEBUG_FILL_STRUCT (layout); g_free (layout); } } LOCAL_SYMBOL void meta_frame_layout_get_borders (const MetaFrameLayout *layout, int text_height, MetaFrameFlags flags, MetaFrameType type, MetaFrameBorders *borders) { int buttons_height, title_height, draggable_borders; meta_frame_borders_clear (borders); /* For a full-screen window, we don't have any borders, visible or not. */ if (flags & META_FRAME_FULLSCREEN) return; g_return_if_fail (layout != NULL); if (!layout->has_title) text_height = 0; buttons_height = layout->button_height + layout->button_border.top + layout->button_border.bottom; title_height = text_height + layout->title_vertical_pad + layout->title_border.top + layout->title_border.bottom; borders->visible.top = MAX (buttons_height, title_height); borders->visible.left = layout->left_width; borders->visible.right = layout->right_width; borders->visible.bottom = layout->bottom_height; draggable_borders = meta_prefs_get_draggable_border_width (); if (flags & META_FRAME_ALLOWS_TOP_RESIZE) { if (type != META_FRAME_TYPE_ATTACHED) borders->invisible.top = MAX (0, draggable_borders - 2); } if (flags & META_FRAME_ALLOWS_BOTTOM_RESIZE) { borders->invisible.bottom = MAX (0, draggable_borders - borders->visible.bottom); } if (flags & META_FRAME_ALLOWS_LEFT_RESIZE) { borders->invisible.left = MAX (0, draggable_borders - borders->visible.left); } if (flags & META_FRAME_ALLOWS_RIGHT_RESIZE) { borders->invisible.right = MAX (0, draggable_borders - borders->visible.right); } borders->total.left = borders->invisible.left + borders->visible.left; borders->total.right = borders->invisible.right + borders->visible.right; borders->total.bottom = borders->invisible.bottom + borders->visible.bottom; borders->total.top = borders->invisible.top + borders->visible.top; } static MetaButtonType map_button_function_to_type (MetaButtonFunction function) { switch (function) { case META_BUTTON_FUNCTION_SHADE: return META_BUTTON_TYPE_SHADE; case META_BUTTON_FUNCTION_ABOVE: return META_BUTTON_TYPE_ABOVE; case META_BUTTON_FUNCTION_STICK: return META_BUTTON_TYPE_STICK; case META_BUTTON_FUNCTION_UNSHADE: return META_BUTTON_TYPE_UNSHADE; case META_BUTTON_FUNCTION_UNABOVE: return META_BUTTON_TYPE_UNABOVE; case META_BUTTON_FUNCTION_UNSTICK: return META_BUTTON_TYPE_UNSTICK; case META_BUTTON_FUNCTION_MENU: return META_BUTTON_TYPE_MENU; case META_BUTTON_FUNCTION_MINIMIZE: return META_BUTTON_TYPE_MINIMIZE; case META_BUTTON_FUNCTION_MAXIMIZE: return META_BUTTON_TYPE_MAXIMIZE; case META_BUTTON_FUNCTION_CLOSE: return META_BUTTON_TYPE_CLOSE; case META_BUTTON_FUNCTION_LAST: return META_BUTTON_TYPE_LAST; } return META_BUTTON_TYPE_LAST; } static MetaButtonSpace* rect_for_function (MetaFrameGeometry *fgeom, MetaFrameFlags flags, MetaButtonFunction function, MetaTheme *theme) { /* Firstly, check version-specific things. */ if (META_THEME_ALLOWS(theme, META_THEME_SHADE_STICK_ABOVE_BUTTONS)) { switch (function) { case META_BUTTON_FUNCTION_SHADE: if ((flags & META_FRAME_ALLOWS_SHADE) && !(flags & META_FRAME_SHADED)) return &fgeom->shade_rect; else return NULL; case META_BUTTON_FUNCTION_ABOVE: if (!(flags & META_FRAME_ABOVE)) return &fgeom->above_rect; else return NULL; case META_BUTTON_FUNCTION_STICK: if (!(flags & META_FRAME_STUCK)) return &fgeom->stick_rect; else return NULL; case META_BUTTON_FUNCTION_UNSHADE: if ((flags & META_FRAME_ALLOWS_SHADE) && (flags & META_FRAME_SHADED)) return &fgeom->unshade_rect; else return NULL; case META_BUTTON_FUNCTION_UNABOVE: if (flags & META_FRAME_ABOVE) return &fgeom->unabove_rect; else return NULL; case META_BUTTON_FUNCTION_UNSTICK: if (flags & META_FRAME_STUCK) return &fgeom->unstick_rect; default: /* just go on to the next switch block */; } } /* now consider the buttons which exist in all versions */ switch (function) { case META_BUTTON_FUNCTION_MENU: if (flags & META_FRAME_ALLOWS_MENU) return &fgeom->menu_rect; else return NULL; case META_BUTTON_FUNCTION_MINIMIZE: if (flags & META_FRAME_ALLOWS_MINIMIZE) return &fgeom->min_rect; else return NULL; case META_BUTTON_FUNCTION_MAXIMIZE: if (flags & META_FRAME_ALLOWS_MAXIMIZE) return &fgeom->max_rect; else return NULL; case META_BUTTON_FUNCTION_CLOSE: if (flags & META_FRAME_ALLOWS_DELETE) return &fgeom->close_rect; else return NULL; case META_BUTTON_FUNCTION_STICK: case META_BUTTON_FUNCTION_SHADE: case META_BUTTON_FUNCTION_ABOVE: case META_BUTTON_FUNCTION_UNSTICK: case META_BUTTON_FUNCTION_UNSHADE: case META_BUTTON_FUNCTION_UNABOVE: /* we are being asked for a >v1 button which hasn't been handled yet, * so obviously we're not in a theme which supports that version. * therefore, we don't show the button. return NULL and all will * be well. */ return NULL; case META_BUTTON_FUNCTION_LAST: return NULL; } return NULL; } static gboolean strip_button (MetaButtonSpace *func_rects[MAX_BUTTONS_PER_CORNER], GdkRectangle *bg_rects[MAX_BUTTONS_PER_CORNER], int *n_rects, MetaButtonSpace *to_strip) { int i; i = 0; while (i < *n_rects) { if (func_rects[i] == to_strip) { *n_rects -= 1; /* shift the other rects back in the array */ while (i < *n_rects) { func_rects[i] = func_rects[i+1]; bg_rects[i] = bg_rects[i+1]; ++i; } func_rects[i] = NULL; bg_rects[i] = NULL; return TRUE; } ++i; } return FALSE; /* did not strip anything */ } LOCAL_SYMBOL void meta_frame_layout_calc_geometry (const MetaFrameLayout *layout, int text_height, MetaFrameFlags flags, int client_width, int client_height, const MetaButtonLayout *button_layout, MetaFrameType type, MetaFrameGeometry *fgeom, MetaTheme *theme) { int i, n_left, n_right, n_left_spacers, n_right_spacers; int x; int button_y; int title_right_edge; int width, height; int button_width, button_height; int min_size_for_rounding; /* the left/right rects in order; the max # of rects * is the number of button functions */ MetaButtonSpace *left_func_rects[MAX_BUTTONS_PER_CORNER]; MetaButtonSpace *right_func_rects[MAX_BUTTONS_PER_CORNER]; GdkRectangle *left_bg_rects[MAX_BUTTONS_PER_CORNER]; gboolean left_buttons_has_spacer[MAX_BUTTONS_PER_CORNER]; GdkRectangle *right_bg_rects[MAX_BUTTONS_PER_CORNER]; gboolean right_buttons_has_spacer[MAX_BUTTONS_PER_CORNER]; MetaFrameBorders borders; meta_frame_layout_get_borders (layout, text_height, flags, type, &borders); fgeom->borders = borders; width = client_width + borders.total.left + borders.total.right; height = ((flags & META_FRAME_SHADED) ? 0: client_height) + borders.total.top + borders.total.bottom; fgeom->width = width; fgeom->height = height; fgeom->top_titlebar_edge = layout->title_border.top; fgeom->bottom_titlebar_edge = layout->title_border.bottom; fgeom->left_titlebar_edge = layout->left_titlebar_edge; fgeom->right_titlebar_edge = layout->right_titlebar_edge; /* gcc warnings */ button_width = -1; button_height = -1; switch (layout->button_sizing) { case META_BUTTON_SIZING_ASPECT: button_height = borders.visible.top - layout->button_border.top - layout->button_border.bottom; button_width = button_height / layout->button_aspect; break; case META_BUTTON_SIZING_FIXED: button_width = layout->button_width; button_height = layout->button_height; break; case META_BUTTON_SIZING_LAST: g_assert_not_reached (); break; } /* FIXME all this code sort of pretends that duplicate buttons * with the same function are allowed, but that breaks the * code in frames.c, so isn't really allowed right now. * Would need left_close_rect, right_close_rect, etc. */ /* Init all button rects to 0, lame hack */ memset (ADDRESS_OF_BUTTON_RECTS (fgeom), '\0', LENGTH_OF_BUTTON_RECTS); n_left = 0; n_right = 0; n_left_spacers = 0; n_right_spacers = 0; if (!layout->hide_buttons) { /* Try to fill in rects */ for (i = 0; i < MAX_BUTTONS_PER_CORNER && button_layout->left_buttons[i] != META_BUTTON_FUNCTION_LAST; i++) { left_func_rects[n_left] = rect_for_function (fgeom, flags, button_layout->left_buttons[i], theme); if (left_func_rects[n_left] != NULL) { left_buttons_has_spacer[n_left] = button_layout->left_buttons_has_spacer[i]; if (button_layout->left_buttons_has_spacer[i]) ++n_left_spacers; ++n_left; } } for (i = 0; i < MAX_BUTTONS_PER_CORNER && button_layout->right_buttons[i] != META_BUTTON_FUNCTION_LAST; i++) { right_func_rects[n_right] = rect_for_function (fgeom, flags, button_layout->right_buttons[i], theme); if (right_func_rects[n_right] != NULL) { right_buttons_has_spacer[n_right] = button_layout->right_buttons_has_spacer[i]; if (button_layout->right_buttons_has_spacer[i]) ++n_right_spacers; ++n_right; } } } for (i = 0; i < MAX_BUTTONS_PER_CORNER; i++) { left_bg_rects[i] = NULL; right_bg_rects[i] = NULL; } for (i = 0; i < n_left; i++) { if (n_left == 1) left_bg_rects[i] = &fgeom->left_single_background; else if (i == 0) left_bg_rects[i] = &fgeom->left_left_background; else if (i == (n_left - 1)) left_bg_rects[i] = &fgeom->left_right_background; else left_bg_rects[i] = &fgeom->left_middle_backgrounds[i - 1]; } for (i = 0; i < n_right; i++) { if (n_right == 1) right_bg_rects[i] = &fgeom->right_single_background; else if (i == (n_right - 1)) right_bg_rects[i] = &fgeom->right_right_background; else if (i == 0) right_bg_rects[i] = &fgeom->right_left_background; else right_bg_rects[i] = &fgeom->right_middle_backgrounds[i - 1]; } /* Be sure buttons fit */ while (n_left > 0 || n_right > 0) { int space_used_by_buttons; int space_available; space_available = fgeom->width - layout->left_titlebar_edge - layout->right_titlebar_edge; space_used_by_buttons = 0; space_used_by_buttons += button_width * n_left; space_used_by_buttons += (button_width * 0.75) * n_left_spacers; space_used_by_buttons += layout->button_border.left * n_left; space_used_by_buttons += layout->button_border.right * n_left; space_used_by_buttons += button_width * n_right; space_used_by_buttons += (button_width * 0.75) * n_right_spacers; space_used_by_buttons += layout->button_border.left * n_right; space_used_by_buttons += layout->button_border.right * n_right; if (space_used_by_buttons <= space_available) break; /* Everything fits, bail out */ /* First try to remove separators */ if (n_left_spacers > 0) { left_buttons_has_spacer[--n_left_spacers] = FALSE; continue; } else if (n_right_spacers > 0) { right_buttons_has_spacer[--n_right_spacers] = FALSE; continue; } /* Otherwise we need to shave out a button. Shave * above, stick, shade, min, max, close, then menu (menu is most useful); * prefer the default button locations. */ if (strip_button (left_func_rects, left_bg_rects, &n_left, &fgeom->above_rect)) continue; else if (strip_button (right_func_rects, right_bg_rects, &n_right, &fgeom->above_rect)) continue; else if (strip_button (left_func_rects, left_bg_rects, &n_left, &fgeom->stick_rect)) continue; else if (strip_button (right_func_rects, right_bg_rects, &n_right, &fgeom->stick_rect)) continue; else if (strip_button (left_func_rects, left_bg_rects, &n_left, &fgeom->shade_rect)) continue; else if (strip_button (right_func_rects, right_bg_rects, &n_right, &fgeom->shade_rect)) continue; else if (strip_button (left_func_rects, left_bg_rects, &n_left, &fgeom->min_rect)) continue; else if (strip_button (right_func_rects, right_bg_rects, &n_right, &fgeom->min_rect)) continue; else if (strip_button (left_func_rects, left_bg_rects, &n_left, &fgeom->max_rect)) continue; else if (strip_button (right_func_rects, right_bg_rects, &n_right, &fgeom->max_rect)) continue; else if (strip_button (left_func_rects, left_bg_rects, &n_left, &fgeom->close_rect)) continue; else if (strip_button (right_func_rects, right_bg_rects, &n_right, &fgeom->close_rect)) continue; else if (strip_button (right_func_rects, right_bg_rects, &n_right, &fgeom->menu_rect)) continue; else if (strip_button (left_func_rects, left_bg_rects, &n_left, &fgeom->menu_rect)) continue; else { meta_bug ("Could not find a button to strip. n_left = %d n_right = %d\n", n_left, n_right); } } /* Save the button layout */ fgeom->button_layout = *button_layout; fgeom->n_left_buttons = n_left; fgeom->n_right_buttons = n_right; /* center buttons vertically */ button_y = (borders.visible.top - (button_height + layout->button_border.top + layout->button_border.bottom)) / 2 + layout->button_border.top + borders.invisible.top; /* right edge of farthest-right button */ x = width - layout->right_titlebar_edge - borders.invisible.right; i = n_right - 1; while (i >= 0) { MetaButtonSpace *rect; if (x < 0) /* if we go negative, leave the buttons we don't get to as 0-width */ break; rect = right_func_rects[i]; rect->visible.x = x - layout->button_border.right - button_width; if (right_buttons_has_spacer[i]) rect->visible.x -= (button_width * 0.75); rect->visible.y = button_y; rect->visible.width = button_width; rect->visible.height = button_height; if (flags & META_FRAME_MAXIMIZED || flags & META_FRAME_TILED_LEFT || flags & META_FRAME_TILED_RIGHT) { rect->clickable.x = rect->visible.x; rect->clickable.y = 0; rect->clickable.width = rect->visible.width; rect->clickable.height = button_height + button_y; if (i == n_right - 1) rect->clickable.width += layout->right_titlebar_edge + layout->right_width + layout->button_border.right; } else g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable)); *(right_bg_rects[i]) = rect->visible; x = rect->visible.x - layout->button_border.left; --i; } /* save right edge of titlebar for later use */ title_right_edge = x - layout->title_border.right; /* Now x changes to be position from the left and we go through * the left-side buttons */ x = layout->left_titlebar_edge + borders.invisible.left; for (i = 0; i < n_left; i++) { MetaButtonSpace *rect; rect = left_func_rects[i]; rect->visible.x = x + layout->button_border.left; rect->visible.y = button_y; rect->visible.width = button_width; rect->visible.height = button_height; if (flags & META_FRAME_MAXIMIZED) { if (i==0) { rect->clickable.x = 0; rect->clickable.width = button_width + x; } else { rect->clickable.x = rect->visible.x; rect->clickable.width = button_width; } rect->clickable.y = 0; rect->clickable.height = button_height + button_y; } else g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable)); x = rect->visible.x + rect->visible.width + layout->button_border.right; if (left_buttons_has_spacer[i]) x += (button_width * 0.75); *(left_bg_rects[i]) = rect->visible; } /* We always fill as much vertical space as possible with title rect, * rather than centering it like the buttons */ fgeom->title_rect.x = x + layout->title_border.left; fgeom->title_rect.y = layout->title_border.top + borders.invisible.top; fgeom->title_rect.width = title_right_edge - fgeom->title_rect.x; fgeom->title_rect.height = borders.visible.top - layout->title_border.top - layout->title_border.bottom; /* Nuke title if it won't fit */ if (fgeom->title_rect.width < 0 || fgeom->title_rect.height < 0) { fgeom->title_rect.width = 0; fgeom->title_rect.height = 0; } if (flags & META_FRAME_SHADED) min_size_for_rounding = 0; else min_size_for_rounding = 5; fgeom->top_left_corner_rounded_radius = 0; fgeom->top_right_corner_rounded_radius = 0; fgeom->bottom_left_corner_rounded_radius = 0; fgeom->bottom_right_corner_rounded_radius = 0; if (borders.visible.top + borders.visible.left >= min_size_for_rounding) fgeom->top_left_corner_rounded_radius = layout->top_left_corner_rounded_radius; if (borders.visible.top + borders.visible.right >= min_size_for_rounding) fgeom->top_right_corner_rounded_radius = layout->top_right_corner_rounded_radius; if (borders.visible.bottom + borders.visible.left >= min_size_for_rounding) fgeom->bottom_left_corner_rounded_radius = layout->bottom_left_corner_rounded_radius; if (borders.visible.bottom + borders.visible.right >= min_size_for_rounding) fgeom->bottom_right_corner_rounded_radius = layout->bottom_right_corner_rounded_radius; } /** * meta_gradient_spec_new: (skip) * */ LOCAL_SYMBOL MetaGradientSpec* meta_gradient_spec_new (MetaGradientType type) { MetaGradientSpec *spec; spec = g_new (MetaGradientSpec, 1); spec->type = type; spec->color_specs = NULL; return spec; } static void free_color_spec (gpointer spec, gpointer user_data) { meta_color_spec_free (spec); } LOCAL_SYMBOL void meta_gradient_spec_free (MetaGradientSpec *spec) { g_return_if_fail (spec != NULL); g_slist_foreach (spec->color_specs, free_color_spec, NULL); g_slist_free (spec->color_specs); DEBUG_FILL_STRUCT (spec); g_free (spec); } LOCAL_SYMBOL GdkPixbuf* meta_gradient_spec_render (const MetaGradientSpec *spec, GtkStyleContext *style, int width, int height) { int n_colors; GdkRGBA *colors; GSList *tmp; int i; GdkPixbuf *pixbuf; n_colors = g_slist_length (spec->color_specs); if (n_colors == 0) return NULL; colors = g_new (GdkRGBA, n_colors); i = 0; tmp = spec->color_specs; while (tmp != NULL) { meta_color_spec_render (tmp->data, style, &colors[i]); tmp = tmp->next; ++i; } pixbuf = meta_gradient_create_multi (width, height, colors, n_colors, spec->type); g_free (colors); return pixbuf; } LOCAL_SYMBOL gboolean meta_gradient_spec_validate (MetaGradientSpec *spec, GError **error) { g_return_val_if_fail (spec != NULL, FALSE); if (g_slist_length (spec->color_specs) < 2) { g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Gradients should have at least two colors")); return FALSE; } return TRUE; } /** * meta_alpha_gradient_spec_new: (skip) * */ LOCAL_SYMBOL LOCAL_SYMBOL MetaAlphaGradientSpec* meta_alpha_gradient_spec_new (MetaGradientType type, int n_alphas) { MetaAlphaGradientSpec *spec; g_return_val_if_fail (n_alphas > 0, NULL); spec = g_new0 (MetaAlphaGradientSpec, 1); spec->type = type; spec->alphas = g_new0 (unsigned char, n_alphas); spec->n_alphas = n_alphas; return spec; } LOCAL_SYMBOL void meta_alpha_gradient_spec_free (MetaAlphaGradientSpec *spec) { g_return_if_fail (spec != NULL); g_free (spec->alphas); g_free (spec); } /** * meta_color_spec_new: (skip) * */ LOCAL_SYMBOL MetaColorSpec* meta_color_spec_new (MetaColorSpecType type) { MetaColorSpec *spec; MetaColorSpec dummy; int size; size = G_STRUCT_OFFSET (MetaColorSpec, data); switch (type) { case META_COLOR_SPEC_BASIC: size += sizeof (dummy.data.basic); break; case META_COLOR_SPEC_GTK: size += sizeof (dummy.data.gtk); break; case META_COLOR_SPEC_GTK_CUSTOM: size += sizeof (dummy.data.gtkcustom); break; case META_COLOR_SPEC_BLEND: size += sizeof (dummy.data.blend); break; case META_COLOR_SPEC_SHADE: size += sizeof (dummy.data.shade); break; } spec = g_malloc0 (size); spec->type = type; return spec; } LOCAL_SYMBOL void meta_color_spec_free (MetaColorSpec *spec) { g_return_if_fail (spec != NULL); switch (spec->type) { case META_COLOR_SPEC_BASIC: DEBUG_FILL_STRUCT (&spec->data.basic); break; case META_COLOR_SPEC_GTK: DEBUG_FILL_STRUCT (&spec->data.gtk); break; case META_COLOR_SPEC_GTK_CUSTOM: if (spec->data.gtkcustom.color_name) g_free (spec->data.gtkcustom.color_name); if (spec->data.gtkcustom.fallback) meta_color_spec_free (spec->data.gtkcustom.fallback); DEBUG_FILL_STRUCT (&spec->data.gtkcustom); break; case META_COLOR_SPEC_BLEND: if (spec->data.blend.foreground) meta_color_spec_free (spec->data.blend.foreground); if (spec->data.blend.background) meta_color_spec_free (spec->data.blend.background); DEBUG_FILL_STRUCT (&spec->data.blend); break; case META_COLOR_SPEC_SHADE: if (spec->data.shade.base) meta_color_spec_free (spec->data.shade.base); DEBUG_FILL_STRUCT (&spec->data.shade); break; } g_free (spec); } /** * meta_color_spec_new_from_string: (skip) * */ LOCAL_SYMBOL MetaColorSpec* meta_color_spec_new_from_string (const char *str, GError **err) { MetaColorSpec *spec; spec = NULL; if (str[0] == 'g' && str[1] == 't' && str[2] == 'k' && str[3] == ':' && str[4] == 'c' && str[5] == 'u' && str[6] == 's' && str[7] == 't' && str[8] == 'o' && str[9] == 'm') { const char *color_name_start, *fallback_str_start, *end; char *color_name; MetaColorSpec *fallback = NULL; static gboolean debug, debug_set = FALSE; if (!debug_set) { debug = g_getenv ("MUFFIN_DISABLE_FALLBACK_COLOR") != NULL; debug_set = TRUE; } if (str[10] != '(') { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("GTK custom color specification must have color name and fallback in parentheses, e.g. gtk:custom(foo,bar); could not parse \"%s\""), str); return NULL; } color_name_start = str + 11; fallback_str_start = color_name_start; while (*fallback_str_start && *fallback_str_start != ',') { if (!(g_ascii_isalnum (*fallback_str_start) || *fallback_str_start == '-' || *fallback_str_start == '_')) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-_ are valid"), *fallback_str_start); return NULL; } fallback_str_start++; } fallback_str_start++; end = strrchr (str, ')'); if (color_name_start == NULL || fallback_str_start == NULL || end == NULL) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not fit the format"), str); return NULL; } if (!debug) { char *fallback_str; fallback_str = g_strndup (fallback_str_start, end - fallback_str_start); fallback = meta_color_spec_new_from_string (fallback_str, err); g_free (fallback_str); } else { fallback = meta_color_spec_new_from_string ("pink", err); } if (fallback == NULL) return NULL; color_name = g_strndup (color_name_start, fallback_str_start - color_name_start - 1); spec = meta_color_spec_new (META_COLOR_SPEC_GTK_CUSTOM); spec->data.gtkcustom.color_name = color_name; spec->data.gtkcustom.fallback = fallback; } else if (str[0] == 'g' && str[1] == 't' && str[2] == 'k' && str[3] == ':') { /* GTK color */ const char *bracket; const char *end_bracket; char *tmp; GtkStateFlags state; MetaGtkColorComponent component; bracket = str; while (*bracket && *bracket != '[') ++bracket; if (*bracket == '\0') { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] where NORMAL is the state; could not parse \"%s\""), str); return NULL; } end_bracket = bracket; ++end_bracket; while (*end_bracket && *end_bracket != ']') ++end_bracket; if (*end_bracket == '\0') { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("GTK color specification must have a close bracket after the state, e.g. gtk:fg[NORMAL] where NORMAL is the state; could not parse \"%s\""), str); return NULL; } tmp = g_strndup (bracket + 1, end_bracket - bracket - 1); state = meta_gtk_state_from_string (tmp); if (((int) state) == -1) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Did not understand state \"%s\" in color specification"), tmp); g_free (tmp); return NULL; } g_free (tmp); tmp = g_strndup (str + 4, bracket - str - 4); component = meta_color_component_from_string (tmp); if (component == META_GTK_COLOR_LAST) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Did not understand color component \"%s\" in color specification"), tmp); g_free (tmp); return NULL; } g_free (tmp); spec = meta_color_spec_new (META_COLOR_SPEC_GTK); spec->data.gtk.state = state; spec->data.gtk.component = component; g_assert (spec->data.gtk.component < META_GTK_COLOR_LAST); } else if (str[0] == 'b' && str[1] == 'l' && str[2] == 'e' && str[3] == 'n' && str[4] == 'd' && str[5] == '/') { /* blend */ char **split; double alpha; char *end; MetaColorSpec *fg; MetaColorSpec *bg; split = g_strsplit (str, "/", 4); if (split[0] == NULL || split[1] == NULL || split[2] == NULL || split[3] == NULL) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the format"), str); g_strfreev (split); return NULL; } alpha = g_ascii_strtod (split[3], &end); if (end == split[3]) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Could not parse alpha value \"%s\" in blended color"), split[3]); g_strfreev (split); return NULL; } if (alpha < (0.0 - 1e6) || alpha > (1.0 + 1e6)) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Alpha value \"%s\" in blended color is not between 0.0 and 1.0"), split[3]); g_strfreev (split); return NULL; } fg = NULL; bg = NULL; bg = meta_color_spec_new_from_string (split[1], err); if (bg == NULL) { g_strfreev (split); return NULL; } fg = meta_color_spec_new_from_string (split[2], err); if (fg == NULL) { meta_color_spec_free (bg); g_strfreev (split); return NULL; } g_strfreev (split); spec = meta_color_spec_new (META_COLOR_SPEC_BLEND); spec->data.blend.alpha = alpha; spec->data.blend.background = bg; spec->data.blend.foreground = fg; } else if (str[0] == 's' && str[1] == 'h' && str[2] == 'a' && str[3] == 'd' && str[4] == 'e' && str[5] == '/') { /* shade */ char **split; double factor; char *end; MetaColorSpec *base; split = g_strsplit (str, "/", 3); if (split[0] == NULL || split[1] == NULL || split[2] == NULL) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"), str); g_strfreev (split); return NULL; } factor = g_ascii_strtod (split[2], &end); if (end == split[2]) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Could not parse shade factor \"%s\" in shaded color"), split[2]); g_strfreev (split); return NULL; } if (factor < (0.0 - 1e6)) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Shade factor \"%s\" in shaded color is negative"), split[2]); g_strfreev (split); return NULL; } base = NULL; base = meta_color_spec_new_from_string (split[1], err); if (base == NULL) { g_strfreev (split); return NULL; } g_strfreev (split); spec = meta_color_spec_new (META_COLOR_SPEC_SHADE); spec->data.shade.factor = factor; spec->data.shade.base = base; } else { spec = meta_color_spec_new (META_COLOR_SPEC_BASIC); if (!gdk_rgba_parse (&spec->data.basic.color, str)) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Could not parse color \"%s\""), str); meta_color_spec_free (spec); return NULL; } } g_assert (spec); return spec; } /** * meta_color_spec_new_gtk: (skip) * */ LOCAL_SYMBOL LOCAL_SYMBOL MetaColorSpec* meta_color_spec_new_gtk (MetaGtkColorComponent component, GtkStateFlags state) { MetaColorSpec *spec; spec = meta_color_spec_new (META_COLOR_SPEC_GTK); spec->data.gtk.component = component; spec->data.gtk.state = state; return spec; } static void get_background_color (GtkStyleContext *context, GtkStateFlags state, GdkRGBA *color) { gtk_style_context_get_background_color (context, state, color); GdkRGBA empty = {0.0, 0.0, 0.0, 0.0}; // Sometimes the widget has no background color, so append the background // class and ask again. if (gdk_rgba_equal(color, &empty)) { gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND); gtk_style_context_get_background_color (context, state, color); } } /* Based on set_color() in gtkstyle.c */ #define LIGHTNESS_MULT 1.3 #define DARKNESS_MULT 0.7 LOCAL_SYMBOL void meta_gtk_style_get_light_color (GtkStyleContext *style, GtkStateFlags state, GdkRGBA *color) { get_background_color (style, state, color); gtk_style_shade (color, color, LIGHTNESS_MULT); } LOCAL_SYMBOL void meta_gtk_style_get_dark_color (GtkStyleContext *style, GtkStateFlags state, GdkRGBA *color) { get_background_color (style, state, color); gtk_style_shade (color, color, DARKNESS_MULT); } static void meta_set_color_from_style (GdkRGBA *color, GtkStyleContext *context, GtkStateFlags state, MetaGtkColorComponent component) { GdkRGBA other; switch (component) { case META_GTK_COLOR_BG: case META_GTK_COLOR_BASE: get_background_color (context, state, color); break; case META_GTK_COLOR_FG: case META_GTK_COLOR_TEXT: gtk_style_context_get_color (context, state, color); break; case META_GTK_COLOR_TEXT_AA: gtk_style_context_get_color (context, state, color); meta_set_color_from_style (&other, context, state, META_GTK_COLOR_BASE); color->red = (color->red + other.red) / 2; color->green = (color->green + other.green) / 2; color->blue = (color->blue + other.blue) / 2; break; case META_GTK_COLOR_MID: meta_gtk_style_get_light_color (context, state, color); meta_gtk_style_get_dark_color (context, state, &other); color->red = (color->red + other.red) / 2; color->green = (color->green + other.green) / 2; color->blue = (color->blue + other.blue) / 2; break; case META_GTK_COLOR_LIGHT: meta_gtk_style_get_light_color (context, state, color); break; case META_GTK_COLOR_DARK: meta_gtk_style_get_dark_color (context, state, color); break; case META_GTK_COLOR_LAST: g_assert_not_reached (); break; } } static void meta_set_custom_color_from_style (GdkRGBA *color, GtkStyleContext *context, char *color_name, MetaColorSpec *fallback) { if (!gtk_style_context_lookup_color (context, color_name, color)) meta_color_spec_render (fallback, context, color); } LOCAL_SYMBOL void meta_color_spec_render (MetaColorSpec *spec, GtkStyleContext *context, GdkRGBA *color) { g_return_if_fail (spec != NULL); g_return_if_fail (GTK_IS_STYLE_CONTEXT (context)); switch (spec->type) { case META_COLOR_SPEC_BASIC: *color = spec->data.basic.color; break; case META_COLOR_SPEC_GTK: meta_set_color_from_style (color, context, spec->data.gtk.state, spec->data.gtk.component); break; case META_COLOR_SPEC_GTK_CUSTOM: meta_set_custom_color_from_style (color, context, spec->data.gtkcustom.color_name, spec->data.gtkcustom.fallback); break; case META_COLOR_SPEC_BLEND: { GdkRGBA bg, fg; meta_color_spec_render (spec->data.blend.background, context, &bg); meta_color_spec_render (spec->data.blend.foreground, context, &fg); color_composite (&bg, &fg, spec->data.blend.alpha, &spec->data.blend.color); *color = spec->data.blend.color; } break; case META_COLOR_SPEC_SHADE: { meta_color_spec_render (spec->data.shade.base, context, &spec->data.shade.color); gtk_style_shade (&spec->data.shade.color, &spec->data.shade.color, spec->data.shade.factor); *color = spec->data.shade.color; } break; } } /* * Represents an operation as a string. * * \param type an operation, such as addition * \return a string, such as "+" */ static const char* op_name (PosOperatorType type) { switch (type) { case POS_OP_ADD: return "+"; case POS_OP_SUBTRACT: return "-"; case POS_OP_MULTIPLY: return "*"; case POS_OP_DIVIDE: return "/"; case POS_OP_MOD: return "%"; case POS_OP_MAX: return "`max`"; case POS_OP_MIN: return "`min`"; case POS_OP_NONE: break; } return ""; } /* * Parses a string and returns an operation. * * \param p a pointer into a string representing an operation; part of an * expression somewhere, so not null-terminated * \param len set to the length of the string found. Set to 0 if none is. * \return the operation found. If none was, returns POS_OP_NONE. */ static PosOperatorType op_from_string (const char *p, int *len) { *len = 0; switch (*p) { case '+': *len = 1; return POS_OP_ADD; case '-': *len = 1; return POS_OP_SUBTRACT; case '*': *len = 1; return POS_OP_MULTIPLY; case '/': *len = 1; return POS_OP_DIVIDE; case '%': *len = 1; return POS_OP_MOD; case '`': if (p[0] == '`' && p[1] == 'm' && p[2] == 'a' && p[3] == 'x' && p[4] == '`') { *len = 5; return POS_OP_MAX; } else if (p[0] == '`' && p[1] == 'm' && p[2] == 'i' && p[3] == 'n' && p[4] == '`') { *len = 5; return POS_OP_MIN; } } return POS_OP_NONE; } /* * Frees an array of tokens. All the tokens and their associated memory * will be freed. * * \param tokens an array of tokens to be freed * \param n_tokens how many tokens are in the array. */ static void free_tokens (PosToken *tokens, int n_tokens) { int i; /* n_tokens can be 0 since tokens may have been allocated more than * it was initialized */ for (i = 0; i < n_tokens; i++) if (tokens[i].type == POS_TOKEN_VARIABLE) g_free (tokens[i].d.v.name); g_free (tokens); } /* * Tokenises a number in an expression. * * \param p a pointer into a string representing an operation; part of an * expression somewhere, so not null-terminated * \param end_return set to a pointer to the end of the number found; but * not updated if no number was found at all * \param next set to either an integer or a float token * \param[out] err set to the problem if there was a problem * \return TRUE if a valid number was found, FALSE otherwise (and "err" will * have been set) * * \bug The "while (*start)..." part: what's wrong with strchr-ish things? * \bug The name is wrong: it doesn't parse anything. * \ingroup tokenizer */ static gboolean parse_number (const char *p, const char **end_return, PosToken *next, GError **err) { const char *start = p; char *end; gboolean is_float; char *num_str; while (*p && (*p == '.' || g_ascii_isdigit (*p))) ++p; if (p == start) { char buf[7] = { '\0' }; buf[g_unichar_to_utf8 (g_utf8_get_char (p), buf)] = '\0'; g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_BAD_CHARACTER, _("Coordinate expression contains character '%s' which is not allowed"), buf); return FALSE; } *end_return = p; /* we need this to exclude floats like "1e6" */ num_str = g_strndup (start, p - start); start = num_str; is_float = FALSE; while (*start) { if (*start == '.') is_float = TRUE; ++start; } if (is_float) { next->type = POS_TOKEN_DOUBLE; next->d.d.val = g_ascii_strtod (num_str, &end); if (end == num_str) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Coordinate expression contains floating point number '%s' which could not be parsed"), num_str); g_free (num_str); return FALSE; } } else { next->type = POS_TOKEN_INT; next->d.i.val = strtol (num_str, &end, 10); if (end == num_str) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Coordinate expression contains integer '%s' which could not be parsed"), num_str); g_free (num_str); return FALSE; } } g_free (num_str); g_assert (next->type == POS_TOKEN_INT || next->type == POS_TOKEN_DOUBLE); return TRUE; } /* * Whether a variable can validly appear as part of the name of a variable. */ #define IS_VARIABLE_CHAR(c) (g_ascii_isalpha ((c)) || (c) == '_') #if 0 static void debug_print_tokens (PosToken *tokens, int n_tokens) { int i; for (i = 0; i < n_tokens; i++) { PosToken *t = &tokens[i]; g_print (" "); switch (t->type) { case POS_TOKEN_INT: g_print ("\"%d\"", t->d.i.val); break; case POS_TOKEN_DOUBLE: g_print ("\"%g\"", t->d.d.val); break; case POS_TOKEN_OPEN_PAREN: g_print ("\"(\""); break; case POS_TOKEN_CLOSE_PAREN: g_print ("\")\""); break; case POS_TOKEN_VARIABLE: g_print ("\"%s\"", t->d.v.name); break; case POS_TOKEN_OPERATOR: g_print ("\"%s\"", op_name (t->d.o.op)); break; } } g_print ("\n"); } #endif /* * Tokenises an expression. * * \param expr The expression * \param[out] tokens_p The resulting tokens * \param[out] n_tokens_p The number of resulting tokens * \param[out] err set to the problem if there was a problem * * \return True if the expression was successfully tokenised; false otherwise. * * \ingroup tokenizer */ static gboolean pos_tokenize (const char *expr, PosToken **tokens_p, int *n_tokens_p, GError **err) { PosToken *tokens; int n_tokens; int allocated; const char *p; *tokens_p = NULL; *n_tokens_p = 0; allocated = 3; n_tokens = 0; tokens = g_new (PosToken, allocated); p = expr; while (*p) { PosToken *next; int len; if (n_tokens == allocated) { allocated *= 2; tokens = g_renew (PosToken, tokens, allocated); } next = &tokens[n_tokens]; switch (*p) { case '*': case '/': case '+': case '-': /* negative numbers aren't allowed so this is easy */ case '%': case '`': next->type = POS_TOKEN_OPERATOR; next->d.o.op = op_from_string (p, &len); if (next->d.o.op != POS_OP_NONE) { ++n_tokens; p = p + (len - 1); /* -1 since we ++p later */ } else { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Coordinate expression contained unknown operator at the start of this text: \"%s\""), p); goto error; } break; case '(': next->type = POS_TOKEN_OPEN_PAREN; ++n_tokens; break; case ')': next->type = POS_TOKEN_CLOSE_PAREN; ++n_tokens; break; case ' ': case '\t': case '\n': break; default: if (IS_VARIABLE_CHAR (*p)) { /* Assume variable */ const char *start = p; while (*p && IS_VARIABLE_CHAR (*p)) ++p; g_assert (p != start); next->type = POS_TOKEN_VARIABLE; next->d.v.name = g_strndup (start, p - start); ++n_tokens; --p; /* since we ++p again at the end of while loop */ } else { /* Assume number */ const char *end; if (!parse_number (p, &end, next, err)) goto error; ++n_tokens; p = end - 1; /* -1 since we ++p again at the end of while loop */ } break; } ++p; } if (n_tokens == 0) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Coordinate expression was empty or not understood")); goto error; } *tokens_p = tokens; *n_tokens_p = n_tokens; return TRUE; error: g_assert (err == NULL || *err != NULL); free_tokens (tokens, n_tokens); return FALSE; } /* * The type of a PosExpr: either integer, double, or an operation. * \ingroup parser */ typedef enum { POS_EXPR_INT, POS_EXPR_DOUBLE, POS_EXPR_OPERATOR } PosExprType; /* * Type and value of an expression in a parsed sequence. We don't * keep expressions in a tree; if this is of type POS_EXPR_OPERATOR, * the arguments of the operator will be in the array positions * immediately preceding and following this operator; they cannot * themselves be operators. * * \bug operator is char; it should really be of PosOperatorType. * \ingroup parser */ typedef struct { PosExprType type; union { double double_val; int int_val; char operator; } d; } PosExpr; #if 0 static void debug_print_exprs (PosExpr *exprs, int n_exprs) { int i; for (i = 0; i < n_exprs; i++) { switch (exprs[i].type) { case POS_EXPR_INT: g_print (" %d", exprs[i].d.int_val); break; case POS_EXPR_DOUBLE: g_print (" %g", exprs[i].d.double_val); break; case POS_EXPR_OPERATOR: g_print (" %s", op_name (exprs[i].d.operator)); break; } } g_print ("\n"); } #endif static gboolean do_operation (PosExpr *a, PosExpr *b, PosOperatorType op, GError **err) { /* Promote types to double if required */ if (a->type == POS_EXPR_DOUBLE || b->type == POS_EXPR_DOUBLE) { if (a->type != POS_EXPR_DOUBLE) { a->type = POS_EXPR_DOUBLE; a->d.double_val = a->d.int_val; } if (b->type != POS_EXPR_DOUBLE) { b->type = POS_EXPR_DOUBLE; b->d.double_val = b->d.int_val; } } g_assert (a->type == b->type); if (a->type == POS_EXPR_INT) { switch (op) { case POS_OP_MULTIPLY: a->d.int_val = a->d.int_val * b->d.int_val; break; case POS_OP_DIVIDE: if (b->d.int_val == 0) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_DIVIDE_BY_ZERO, _("Coordinate expression results in division by zero")); return FALSE; } a->d.int_val = a->d.int_val / b->d.int_val; break; case POS_OP_MOD: if (b->d.int_val == 0) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_DIVIDE_BY_ZERO, _("Coordinate expression results in division by zero")); return FALSE; } a->d.int_val = a->d.int_val % b->d.int_val; break; case POS_OP_ADD: a->d.int_val = a->d.int_val + b->d.int_val; break; case POS_OP_SUBTRACT: a->d.int_val = a->d.int_val - b->d.int_val; break; case POS_OP_MAX: a->d.int_val = MAX (a->d.int_val, b->d.int_val); break; case POS_OP_MIN: a->d.int_val = MIN (a->d.int_val, b->d.int_val); break; case POS_OP_NONE: g_assert_not_reached (); break; } } else if (a->type == POS_EXPR_DOUBLE) { switch (op) { case POS_OP_MULTIPLY: a->d.double_val = a->d.double_val * b->d.double_val; break; case POS_OP_DIVIDE: if (b->d.double_val == 0.0) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_DIVIDE_BY_ZERO, _("Coordinate expression results in division by zero")); return FALSE; } a->d.double_val = a->d.double_val / b->d.double_val; break; case POS_OP_MOD: g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_MOD_ON_FLOAT, _("Coordinate expression tries to use mod operator on a floating-point number")); return FALSE; case POS_OP_ADD: a->d.double_val = a->d.double_val + b->d.double_val; break; case POS_OP_SUBTRACT: a->d.double_val = a->d.double_val - b->d.double_val; break; case POS_OP_MAX: a->d.double_val = MAX (a->d.double_val, b->d.double_val); break; case POS_OP_MIN: a->d.double_val = MIN (a->d.double_val, b->d.double_val); break; case POS_OP_NONE: g_assert_not_reached (); break; } } else g_assert_not_reached (); return TRUE; } static gboolean do_operations (PosExpr *exprs, int *n_exprs, int precedence, GError **err) { int i; #if 0 g_print ("Doing prec %d ops on %d exprs\n", precedence, *n_exprs); debug_print_exprs (exprs, *n_exprs); #endif i = 1; while (i < *n_exprs) { gboolean compress; /* exprs[i-1] first operand * exprs[i] operator * exprs[i+1] second operand * * we replace first operand with result of mul/div/mod, * or skip over operator and second operand if we have * an add/subtract */ if (exprs[i-1].type == POS_EXPR_OPERATOR) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Coordinate expression has an operator \"%s\" where an operand was expected"), op_name (exprs[i-1].d.operator)); return FALSE; } if (exprs[i].type != POS_EXPR_OPERATOR) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Coordinate expression had an operand where an operator was expected")); return FALSE; } if (i == (*n_exprs - 1)) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Coordinate expression ended with an operator instead of an operand")); return FALSE; } g_assert ((i+1) < *n_exprs); if (exprs[i+1].type == POS_EXPR_OPERATOR) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Coordinate expression has operator \"%c\" following operator \"%c\" with no operand in between"), exprs[i+1].d.operator, exprs[i].d.operator); return FALSE; } compress = FALSE; switch (precedence) { case 2: switch (exprs[i].d.operator) { case POS_OP_DIVIDE: case POS_OP_MOD: case POS_OP_MULTIPLY: compress = TRUE; if (!do_operation (&exprs[i-1], &exprs[i+1], exprs[i].d.operator, err)) return FALSE; break; } break; case 1: switch (exprs[i].d.operator) { case POS_OP_ADD: case POS_OP_SUBTRACT: compress = TRUE; if (!do_operation (&exprs[i-1], &exprs[i+1], exprs[i].d.operator, err)) return FALSE; break; } break; /* I have no rationale at all for making these low-precedence */ case 0: switch (exprs[i].d.operator) { case POS_OP_MAX: case POS_OP_MIN: compress = TRUE; if (!do_operation (&exprs[i-1], &exprs[i+1], exprs[i].d.operator, err)) return FALSE; break; } break; } if (compress) { /* exprs[i-1] first operand (now result) * exprs[i] operator * exprs[i+1] second operand * exprs[i+2] new operator * * we move new operator just after first operand */ if ((i+2) < *n_exprs) { g_memmove (&exprs[i], &exprs[i+2], sizeof (PosExpr) * (*n_exprs - i - 2)); } *n_exprs -= 2; } else { /* Skip operator and next operand */ i += 2; } } return TRUE; } /* * There is a predefined set of variables which can appear in an expression. * Here we take a token representing a variable, and return the current value * of that variable in a particular environment. * (The value is always an integer.) * * There are supposedly some circumstances in which this function can be * called from outside Metacity, in which case env->theme will be NULL, and * therefore we can't use it to find out quark values, so we do the comparison * using strcmp, which is slower. * * \param t The token representing a variable * \param[out] result The value of that variable; not set if the token did * not represent a known variable * \param env The environment within which t should be evaluated * \param[out] err set to the problem if there was a problem * * \return true if we found the variable asked for, false if we didn't * * \bug shouldn't t be const? * \bug we should perhaps consider some sort of lookup arrangement into an * array; also, the duplication of code is unlovely; perhaps using glib * string hashes instead of quarks would fix both problems? * \ingroup parser */ static gboolean pos_eval_get_variable (PosToken *t, int *result, const MetaPositionExprEnv *env, GError **err) { if (env->theme) { if (t->d.v.name_quark == env->theme->quark_width) *result = env->rect.width; else if (t->d.v.name_quark == env->theme->quark_height) *result = env->rect.height; else if (env->object_width >= 0 && t->d.v.name_quark == env->theme->quark_object_width) *result = env->object_width; else if (env->object_height >= 0 && t->d.v.name_quark == env->theme->quark_object_height) *result = env->object_height; else if (t->d.v.name_quark == env->theme->quark_left_width) *result = env->left_width; else if (t->d.v.name_quark == env->theme->quark_right_width) *result = env->right_width; else if (t->d.v.name_quark == env->theme->quark_top_height) *result = env->top_height; else if (t->d.v.name_quark == env->theme->quark_bottom_height) *result = env->bottom_height; else if (t->d.v.name_quark == env->theme->quark_mini_icon_width) *result = env->mini_icon_width; else if (t->d.v.name_quark == env->theme->quark_mini_icon_height) *result = env->mini_icon_height; else if (t->d.v.name_quark == env->theme->quark_icon_width) *result = env->icon_width; else if (t->d.v.name_quark == env->theme->quark_icon_height) *result = env->icon_height; else if (t->d.v.name_quark == env->theme->quark_title_width) *result = env->title_width; else if (t->d.v.name_quark == env->theme->quark_title_height) *result = env->title_height; else if (t->d.v.name_quark == env->theme->quark_frame_x_center) *result = env->frame_x_center; else if (t->d.v.name_quark == env->theme->quark_frame_y_center) *result = env->frame_y_center; else { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_UNKNOWN_VARIABLE, _("Coordinate expression had unknown variable or constant \"%s\""), t->d.v.name); return FALSE; } } else { if (strcmp (t->d.v.name, "width") == 0) *result = env->rect.width; else if (strcmp (t->d.v.name, "height") == 0) *result = env->rect.height; else if (env->object_width >= 0 && strcmp (t->d.v.name, "object_width") == 0) *result = env->object_width; else if (env->object_height >= 0 && strcmp (t->d.v.name, "object_height") == 0) *result = env->object_height; else if (strcmp (t->d.v.name, "left_width") == 0) *result = env->left_width; else if (strcmp (t->d.v.name, "right_width") == 0) *result = env->right_width; else if (strcmp (t->d.v.name, "top_height") == 0) *result = env->top_height; else if (strcmp (t->d.v.name, "bottom_height") == 0) *result = env->bottom_height; else if (strcmp (t->d.v.name, "mini_icon_width") == 0) *result = env->mini_icon_width; else if (strcmp (t->d.v.name, "mini_icon_height") == 0) *result = env->mini_icon_height; else if (strcmp (t->d.v.name, "icon_width") == 0) *result = env->icon_width; else if (strcmp (t->d.v.name, "icon_height") == 0) *result = env->icon_height; else if (strcmp (t->d.v.name, "title_width") == 0) *result = env->title_width; else if (strcmp (t->d.v.name, "title_height") == 0) *result = env->title_height; else if (strcmp (t->d.v.name, "frame_x_center") == 0) *result = env->frame_x_center; else if (strcmp (t->d.v.name, "frame_y_center") == 0) *result = env->frame_y_center; else { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_UNKNOWN_VARIABLE, _("Coordinate expression had unknown variable or constant \"%s\""), t->d.v.name); return FALSE; } } return TRUE; } /* * Evaluates a sequence of tokens within a particular environment context, * and returns the current value. May recur if parantheses are found. * * \param tokens A list of tokens to evaluate. * \param n_tokens How many tokens are in the list. * \param env The environment context in which to evaluate the expression. * \param[out] result The current value of the expression * * \bug Yes, we really do reparse the expression every time it's evaluated. * We should keep the parse tree around all the time and just * run the new values through it. * \ingroup parser */ static gboolean pos_eval_helper (PosToken *tokens, int n_tokens, const MetaPositionExprEnv *env, PosExpr *result, GError **err) { /* Lazy-ass hardcoded limit on number of terms in expression */ #define MAX_EXPRS 32 int paren_level; int first_paren; int i; PosExpr exprs[MAX_EXPRS]; int n_exprs; int precedence; /* Our first goal is to get a list of PosExpr, essentially * substituting variables and handling parentheses. */ first_paren = 0; paren_level = 0; n_exprs = 0; for (i = 0; i < n_tokens; i++) { PosToken *t = &tokens[i]; if (n_exprs >= MAX_EXPRS) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Coordinate expression parser overflowed its buffer.")); return FALSE; } if (paren_level == 0) { switch (t->type) { case POS_TOKEN_INT: exprs[n_exprs].type = POS_EXPR_INT; exprs[n_exprs].d.int_val = t->d.i.val; ++n_exprs; break; case POS_TOKEN_DOUBLE: exprs[n_exprs].type = POS_EXPR_DOUBLE; exprs[n_exprs].d.double_val = t->d.d.val; ++n_exprs; break; case POS_TOKEN_OPEN_PAREN: ++paren_level; if (paren_level == 1) first_paren = i; break; case POS_TOKEN_CLOSE_PAREN: g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_BAD_PARENS, _("Coordinate expression had a close parenthesis with no open parenthesis")); return FALSE; case POS_TOKEN_VARIABLE: exprs[n_exprs].type = POS_EXPR_INT; /* FIXME we should just dump all this crap * in a hash, maybe keep width/height out * for optimization purposes */ if (!pos_eval_get_variable (t, &exprs[n_exprs].d.int_val, env, err)) return FALSE; ++n_exprs; break; case POS_TOKEN_OPERATOR: exprs[n_exprs].type = POS_EXPR_OPERATOR; exprs[n_exprs].d.operator = t->d.o.op; ++n_exprs; break; } } else { g_assert (paren_level > 0); switch (t->type) { case POS_TOKEN_INT: case POS_TOKEN_DOUBLE: case POS_TOKEN_VARIABLE: case POS_TOKEN_OPERATOR: break; case POS_TOKEN_OPEN_PAREN: ++paren_level; break; case POS_TOKEN_CLOSE_PAREN: if (paren_level == 1) { /* We closed a toplevel paren group, so recurse */ if (!pos_eval_helper (&tokens[first_paren+1], i - first_paren - 1, env, &exprs[n_exprs], err)) return FALSE; ++n_exprs; } --paren_level; break; } } } if (paren_level > 0) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_BAD_PARENS, _("Coordinate expression had an open parenthesis with no close parenthesis")); return FALSE; } /* Now we have no parens and no vars; so we just do all the multiplies * and divides, then all the add and subtract. */ if (n_exprs == 0) { g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("Coordinate expression doesn't seem to have any operators or operands")); return FALSE; } /* precedence 1 ops */ precedence = 2; while (precedence >= 0) { if (!do_operations (exprs, &n_exprs, precedence, err)) return FALSE; --precedence; } g_assert (n_exprs == 1); *result = *exprs; return TRUE; } /* * expr = int | double | expr * expr | expr / expr | * expr + expr | expr - expr | (expr) * * so very not worth fooling with bison, yet so very painful by hand. */ /* * Evaluates an expression. * * \param spec The expression to evaluate. * \param env The environment context to evaluate the expression in. * \param[out] val_p The integer value of the expression; if the expression * is of type float, this will be rounded. If we return * FALSE because the expression is invalid, this will be * zero. * \param[out] err The error, if anything went wrong. * * \return True if we evaluated the expression successfully; false otherwise. * * \bug Shouldn't spec be const? * \ingroup parser */ static gboolean pos_eval (MetaDrawSpec *spec, const MetaPositionExprEnv *env, int *val_p, GError **err) { PosExpr expr; *val_p = 0; if (pos_eval_helper (spec->tokens, spec->n_tokens, env, &expr, err)) { switch (expr.type) { case POS_EXPR_INT: *val_p = expr.d.int_val; break; case POS_EXPR_DOUBLE: *val_p = expr.d.double_val; break; case POS_EXPR_OPERATOR: g_assert_not_reached (); break; } return TRUE; } else { return FALSE; } } /* We always return both X and Y, but only one will be meaningful in * most contexts. */ /** * meta_parse_position_expression: (skip) * */ LOCAL_SYMBOL gboolean meta_parse_position_expression (MetaDrawSpec *spec, const MetaPositionExprEnv *env, int *x_return, int *y_return, GError **err) { /* All positions are in a coordinate system with x, y at the origin. * The expression can have -, +, *, / as operators, floating point * or integer constants, and the variables "width" and "height" and * optionally "object_width" and object_height". Negative numbers * aren't allowed. */ int val; if (spec->constant) val = spec->value; else { if (pos_eval (spec, env, &spec->value, err) == FALSE) { g_assert (err == NULL || *err != NULL); return FALSE; } val = spec->value; } if (x_return) *x_return = env->rect.x + val; if (y_return) *y_return = env->rect.y + val; return TRUE; } /** * meta_parse_size_expression: (skip) * */ LOCAL_SYMBOL gboolean meta_parse_size_expression (MetaDrawSpec *spec, const MetaPositionExprEnv *env, int *val_return, GError **err) { int val; if (spec->constant) val = spec->value; else { if (pos_eval (spec, env, &spec->value, err) == FALSE) { g_assert (err == NULL || *err != NULL); return FALSE; } val = spec->value; } if (val_return) *val_return = MAX (val, 1); /* require that sizes be at least 1x1 */ return TRUE; } /* To do this we tokenize, replace variable tokens * that are constants, then reassemble. The purpose * here is to optimize expressions so we don't do hash * lookups to eval them. Obviously it's a tradeoff that * slows down theme load times. */ LOCAL_SYMBOL gboolean meta_theme_replace_constants (MetaTheme *theme, PosToken *tokens, int n_tokens, GError **err) { int i; double dval; int ival; gboolean is_constant = TRUE; /* Loop through tokenized string looking for variables to replace */ for (i = 0; i < n_tokens; i++) { PosToken *t = &tokens[i]; if (t->type == POS_TOKEN_VARIABLE) { if (meta_theme_lookup_int_constant (theme, t->d.v.name, &ival)) { g_free (t->d.v.name); t->type = POS_TOKEN_INT; t->d.i.val = ival; } else if (meta_theme_lookup_float_constant (theme, t->d.v.name, &dval)) { g_free (t->d.v.name); t->type = POS_TOKEN_DOUBLE; t->d.d.val = dval; } else { /* If we've found a variable that cannot be replaced then the expression is not a constant expression and we want to replace it with a GQuark */ t->d.v.name_quark = g_quark_from_string (t->d.v.name); is_constant = FALSE; } } } return is_constant; } static int parse_x_position_unchecked (MetaDrawSpec *spec, const MetaPositionExprEnv *env) { int retval; GError *error; retval = 0; error = NULL; if (!meta_parse_position_expression (spec, env, &retval, NULL, &error)) { meta_warning (_("Theme contained an expression that resulted in an error: %s\n"), error->message); g_error_free (error); } return retval; } static int parse_y_position_unchecked (MetaDrawSpec *spec, const MetaPositionExprEnv *env) { int retval; GError *error; retval = 0; error = NULL; if (!meta_parse_position_expression (spec, env, NULL, &retval, &error)) { meta_warning (_("Theme contained an expression that resulted in an error: %s\n"), error->message); g_error_free (error); } return retval; } static int parse_size_unchecked (MetaDrawSpec *spec, MetaPositionExprEnv *env) { int retval; GError *error; retval = 0; error = NULL; if (!meta_parse_size_expression (spec, env, &retval, &error)) { meta_warning (_("Theme contained an expression that resulted in an error: %s\n"), error->message); g_error_free (error); } return retval; } LOCAL_SYMBOL void meta_draw_spec_free (MetaDrawSpec *spec) { if (!spec) return; free_tokens (spec->tokens, spec->n_tokens); g_slice_free (MetaDrawSpec, spec); } /** * meta_draw_spec_new: (skip) * */ LOCAL_SYMBOL MetaDrawSpec * meta_draw_spec_new (MetaTheme *theme, const char *expr, GError **error) { MetaDrawSpec *spec; spec = g_slice_new0 (MetaDrawSpec); pos_tokenize (expr, &spec->tokens, &spec->n_tokens, NULL); spec->constant = meta_theme_replace_constants (theme, spec->tokens, spec->n_tokens, NULL); if (spec->constant) { gboolean result; result = pos_eval (spec, NULL, &spec->value, error); if (result == FALSE) { meta_draw_spec_free (spec); return NULL; } } return spec; } /** * meta_draw_op_new: (skip) * */ LOCAL_SYMBOL MetaDrawOp* meta_draw_op_new (MetaDrawType type) { MetaDrawOp *op; MetaDrawOp dummy; int size; size = G_STRUCT_OFFSET (MetaDrawOp, data); switch (type) { case META_DRAW_LINE: size += sizeof (dummy.data.line); break; case META_DRAW_RECTANGLE: size += sizeof (dummy.data.rectangle); break; case META_DRAW_ARC: size += sizeof (dummy.data.arc); break; case META_DRAW_CLIP: size += sizeof (dummy.data.clip); break; case META_DRAW_TINT: size += sizeof (dummy.data.tint); break; case META_DRAW_GRADIENT: size += sizeof (dummy.data.gradient); break; case META_DRAW_IMAGE: size += sizeof (dummy.data.image); break; case META_DRAW_GTK_ARROW: size += sizeof (dummy.data.gtk_arrow); break; case META_DRAW_GTK_BOX: size += sizeof (dummy.data.gtk_box); break; case META_DRAW_GTK_VLINE: size += sizeof (dummy.data.gtk_vline); break; case META_DRAW_ICON: size += sizeof (dummy.data.icon); break; case META_DRAW_TITLE: size += sizeof (dummy.data.title); break; case META_DRAW_OP_LIST: size += sizeof (dummy.data.op_list); break; case META_DRAW_TILE: size += sizeof (dummy.data.tile); break; } op = g_malloc0 (size); op->type = type; return op; } LOCAL_SYMBOL void meta_draw_op_free (MetaDrawOp *op) { g_return_if_fail (op != NULL); switch (op->type) { case META_DRAW_LINE: if (op->data.line.color_spec) meta_color_spec_free (op->data.line.color_spec); meta_draw_spec_free (op->data.line.x1); meta_draw_spec_free (op->data.line.y1); meta_draw_spec_free (op->data.line.x2); meta_draw_spec_free (op->data.line.y2); break; case META_DRAW_RECTANGLE: if (op->data.rectangle.color_spec) g_free (op->data.rectangle.color_spec); meta_draw_spec_free (op->data.rectangle.x); meta_draw_spec_free (op->data.rectangle.y); meta_draw_spec_free (op->data.rectangle.width); meta_draw_spec_free (op->data.rectangle.height); break; case META_DRAW_ARC: if (op->data.arc.color_spec) g_free (op->data.arc.color_spec); meta_draw_spec_free (op->data.arc.x); meta_draw_spec_free (op->data.arc.y); meta_draw_spec_free (op->data.arc.width); meta_draw_spec_free (op->data.arc.height); break; case META_DRAW_CLIP: meta_draw_spec_free (op->data.clip.x); meta_draw_spec_free (op->data.clip.y); meta_draw_spec_free (op->data.clip.width); meta_draw_spec_free (op->data.clip.height); break; case META_DRAW_TINT: if (op->data.tint.color_spec) meta_color_spec_free (op->data.tint.color_spec); if (op->data.tint.alpha_spec) meta_alpha_gradient_spec_free (op->data.tint.alpha_spec); meta_draw_spec_free (op->data.tint.x); meta_draw_spec_free (op->data.tint.y); meta_draw_spec_free (op->data.tint.width); meta_draw_spec_free (op->data.tint.height); break; case META_DRAW_GRADIENT: if (op->data.gradient.gradient_spec) meta_gradient_spec_free (op->data.gradient.gradient_spec); if (op->data.gradient.alpha_spec) meta_alpha_gradient_spec_free (op->data.gradient.alpha_spec); meta_draw_spec_free (op->data.gradient.x); meta_draw_spec_free (op->data.gradient.y); meta_draw_spec_free (op->data.gradient.width); meta_draw_spec_free (op->data.gradient.height); break; case META_DRAW_IMAGE: if (op->data.image.alpha_spec) meta_alpha_gradient_spec_free (op->data.image.alpha_spec); if (op->data.image.pixbuf) g_object_unref (G_OBJECT (op->data.image.pixbuf)); if (op->data.image.colorize_spec) meta_color_spec_free (op->data.image.colorize_spec); if (op->data.image.colorize_cache_pixbuf) g_object_unref (G_OBJECT (op->data.image.colorize_cache_pixbuf)); meta_draw_spec_free (op->data.image.x); meta_draw_spec_free (op->data.image.y); meta_draw_spec_free (op->data.image.width); meta_draw_spec_free (op->data.image.height); break; case META_DRAW_GTK_ARROW: meta_draw_spec_free (op->data.gtk_arrow.x); meta_draw_spec_free (op->data.gtk_arrow.y); meta_draw_spec_free (op->data.gtk_arrow.width); meta_draw_spec_free (op->data.gtk_arrow.height); break; case META_DRAW_GTK_BOX: meta_draw_spec_free (op->data.gtk_box.x); meta_draw_spec_free (op->data.gtk_box.y); meta_draw_spec_free (op->data.gtk_box.width); meta_draw_spec_free (op->data.gtk_box.height); break; case META_DRAW_GTK_VLINE: meta_draw_spec_free (op->data.gtk_vline.x); meta_draw_spec_free (op->data.gtk_vline.y1); meta_draw_spec_free (op->data.gtk_vline.y2); break; case META_DRAW_ICON: if (op->data.icon.alpha_spec) meta_alpha_gradient_spec_free (op->data.icon.alpha_spec); meta_draw_spec_free (op->data.icon.x); meta_draw_spec_free (op->data.icon.y); meta_draw_spec_free (op->data.icon.width); meta_draw_spec_free (op->data.icon.height); break; case META_DRAW_TITLE: if (op->data.title.color_spec) meta_color_spec_free (op->data.title.color_spec); meta_draw_spec_free (op->data.title.x); meta_draw_spec_free (op->data.title.y); if (op->data.title.ellipsize_width) meta_draw_spec_free (op->data.title.ellipsize_width); break; case META_DRAW_OP_LIST: if (op->data.op_list.op_list) meta_draw_op_list_unref (op->data.op_list.op_list); meta_draw_spec_free (op->data.op_list.x); meta_draw_spec_free (op->data.op_list.y); meta_draw_spec_free (op->data.op_list.width); meta_draw_spec_free (op->data.op_list.height); break; case META_DRAW_TILE: if (op->data.tile.op_list) meta_draw_op_list_unref (op->data.tile.op_list); meta_draw_spec_free (op->data.tile.x); meta_draw_spec_free (op->data.tile.y); meta_draw_spec_free (op->data.tile.width); meta_draw_spec_free (op->data.tile.height); meta_draw_spec_free (op->data.tile.tile_xoffset); meta_draw_spec_free (op->data.tile.tile_yoffset); meta_draw_spec_free (op->data.tile.tile_width); meta_draw_spec_free (op->data.tile.tile_height); break; } g_free (op); } static GdkPixbuf* apply_alpha (GdkPixbuf *pixbuf, MetaAlphaGradientSpec *spec, gboolean force_copy) { GdkPixbuf *new_pixbuf; gboolean needs_alpha; g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL); needs_alpha = spec && (spec->n_alphas > 1 || spec->alphas[0] != 0xff); if (!needs_alpha) return pixbuf; if (!gdk_pixbuf_get_has_alpha (pixbuf)) { new_pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0); g_object_unref (G_OBJECT (pixbuf)); pixbuf = new_pixbuf; } else if (force_copy) { new_pixbuf = gdk_pixbuf_copy (pixbuf); g_object_unref (G_OBJECT (pixbuf)); pixbuf = new_pixbuf; } g_assert (gdk_pixbuf_get_has_alpha (pixbuf)); meta_gradient_add_alpha (pixbuf, spec->alphas, spec->n_alphas, spec->type); return pixbuf; } static GdkPixbuf* pixbuf_tile (GdkPixbuf *tile, int width, int height) { GdkPixbuf *pixbuf; int tile_width; int tile_height; int i, j; tile_width = gdk_pixbuf_get_width (tile); tile_height = gdk_pixbuf_get_height (tile); pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, gdk_pixbuf_get_has_alpha (tile), 8, width, height); i = 0; while (i < width) { j = 0; while (j < height) { int w, h; w = MIN (tile_width, width - i); h = MIN (tile_height, height - j); gdk_pixbuf_copy_area (tile, 0, 0, w, h, pixbuf, i, j); j += tile_height; } i += tile_width; } return pixbuf; } static GdkPixbuf * replicate_rows (GdkPixbuf *src, int src_x, int src_y, int width, int height) { unsigned int n_channels = gdk_pixbuf_get_n_channels (src); unsigned int src_rowstride = gdk_pixbuf_get_rowstride (src); unsigned char *pixels = (gdk_pixbuf_get_pixels (src) + src_y * src_rowstride + src_x * n_channels); unsigned char *dest_pixels; GdkPixbuf *result; unsigned int dest_rowstride; int i; result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8, width, height); dest_rowstride = gdk_pixbuf_get_rowstride (result); dest_pixels = gdk_pixbuf_get_pixels (result); for (i = 0; i < height; i++) memcpy (dest_pixels + dest_rowstride * i, pixels, n_channels * width); return result; } static GdkPixbuf * replicate_cols (GdkPixbuf *src, int src_x, int src_y, int width, int height) { unsigned int n_channels = gdk_pixbuf_get_n_channels (src); unsigned int src_rowstride = gdk_pixbuf_get_rowstride (src); unsigned char *pixels = (gdk_pixbuf_get_pixels (src) + src_y * src_rowstride + src_x * n_channels); unsigned char *dest_pixels; GdkPixbuf *result; unsigned int dest_rowstride; int i, j; result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8, width, height); dest_rowstride = gdk_pixbuf_get_rowstride (result); dest_pixels = gdk_pixbuf_get_pixels (result); for (i = 0; i < height; i++) { unsigned char *p = dest_pixels + dest_rowstride * i; unsigned char *q = pixels + src_rowstride * i; unsigned char r = *(q++); unsigned char g = *(q++); unsigned char b = *(q++); if (n_channels == 4) { unsigned char a; a = *(q++); for (j = 0; j < width; j++) { *(p++) = r; *(p++) = g; *(p++) = b; *(p++) = a; } } else { for (j = 0; j < width; j++) { *(p++) = r; *(p++) = g; *(p++) = b; } } } return result; } /* gdk_pixbuf_scale_simple doesn't do too well with scaling a pixel or two up or down, you end up with a blurry icon. Avoid scaling the icon if the scaled size difference is within our arbitrary tolerance. This isn't perfect.. if you use a crazy-sized window title font, your icons still may end up less than ideal, but for most users, this will solve things. It would be more effective to avoid scaling at all, and load the image from a file directly here (especially with SVG images,) but images are used in some themes to construct frames and I don't want to affect that. There are also unknown performance implications to loading here every time a window is added) */ #define PIXBUF_SIZE_TOLERANCE 2 static gboolean in_tolerance_to (gint size, gint scale_size) { return scale_size <= size + PIXBUF_SIZE_TOLERANCE && scale_size >= size - PIXBUF_SIZE_TOLERANCE; } static GdkPixbuf* scale_and_alpha_pixbuf (GdkPixbuf *src, MetaAlphaGradientSpec *alpha_spec, MetaImageFillType fill_type, int width, int height, gboolean vertical_stripes, gboolean horizontal_stripes) { GdkPixbuf *pixbuf; GdkPixbuf *temp_pixbuf; pixbuf = NULL; pixbuf = src; if (gdk_pixbuf_get_width (pixbuf) == width && gdk_pixbuf_get_height (pixbuf) == height) { g_object_ref (G_OBJECT (pixbuf)); } else { if (fill_type == META_IMAGE_FILL_TILE) { pixbuf = pixbuf_tile (pixbuf, width, height); } else { int src_h, src_w, dest_h, dest_w; src_h = gdk_pixbuf_get_height (src); src_w = gdk_pixbuf_get_width (src); /* prefer to replicate_cols if possible, as that * is faster (no memory reads) */ if (horizontal_stripes) { dest_w = gdk_pixbuf_get_width (src); dest_h = height; } else if (vertical_stripes) { dest_w = width; dest_h = gdk_pixbuf_get_height (src); } else { dest_w = width; dest_h = height; } if (in_tolerance_to (src_w, dest_w) && in_tolerance_to (src_h, dest_h)) { temp_pixbuf = src; g_object_ref (G_OBJECT (temp_pixbuf)); } else { temp_pixbuf = gdk_pixbuf_scale_simple (src, dest_w, dest_h, GDK_INTERP_BILINEAR); } /* prefer to replicate_cols if possible, as that * is faster (no memory reads) */ if (horizontal_stripes) { pixbuf = replicate_cols (temp_pixbuf, 0, 0, width, height); g_object_unref (G_OBJECT (temp_pixbuf)); } else if (vertical_stripes) { pixbuf = replicate_rows (temp_pixbuf, 0, 0, width, height); g_object_unref (G_OBJECT (temp_pixbuf)); } else { pixbuf = temp_pixbuf; } } } if (pixbuf) pixbuf = apply_alpha (pixbuf, alpha_spec, pixbuf == src); return pixbuf; } static GdkPixbuf* draw_op_as_pixbuf (const MetaDrawOp *op, GtkStyleContext *context, const MetaDrawInfo *info, int width, int height) { /* Try to get the op as a pixbuf, assuming w/h in the op * matches the width/height passed in. return NULL * if the op can't be converted to an equivalent pixbuf. */ GdkPixbuf *pixbuf; pixbuf = NULL; switch (op->type) { case META_DRAW_LINE: break; case META_DRAW_RECTANGLE: if (op->data.rectangle.filled) { GdkRGBA color; meta_color_spec_render (op->data.rectangle.color_spec, context, &color); pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height); gdk_pixbuf_fill (pixbuf, GDK_COLOR_RGBA (color)); } break; case META_DRAW_ARC: break; case META_DRAW_CLIP: break; case META_DRAW_TINT: { GdkRGBA color; guint32 rgba; gboolean has_alpha; meta_color_spec_render (op->data.rectangle.color_spec, context, &color); has_alpha = op->data.tint.alpha_spec && (op->data.tint.alpha_spec->n_alphas > 1 || op->data.tint.alpha_spec->alphas[0] != 0xff); pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, has_alpha, 8, width, height); if (!has_alpha) { rgba = GDK_COLOR_RGBA (color); gdk_pixbuf_fill (pixbuf, rgba); } else if (op->data.tint.alpha_spec->n_alphas == 1) { rgba = GDK_COLOR_RGBA (color); rgba &= ~0xff; rgba |= op->data.tint.alpha_spec->alphas[0]; gdk_pixbuf_fill (pixbuf, rgba); } else { rgba = GDK_COLOR_RGBA (color); gdk_pixbuf_fill (pixbuf, rgba); meta_gradient_add_alpha (pixbuf, op->data.tint.alpha_spec->alphas, op->data.tint.alpha_spec->n_alphas, op->data.tint.alpha_spec->type); } } break; case META_DRAW_GRADIENT: { pixbuf = meta_gradient_spec_render (op->data.gradient.gradient_spec, context, width, height); pixbuf = apply_alpha (pixbuf, op->data.gradient.alpha_spec, FALSE); } break; case META_DRAW_IMAGE: { if (op->data.image.colorize_spec) { GdkRGBA color; meta_color_spec_render (op->data.image.colorize_spec, context, &color); if (op->data.image.colorize_cache_pixbuf == NULL || op->data.image.colorize_cache_pixel != GDK_COLOR_RGB (color)) { if (op->data.image.colorize_cache_pixbuf) g_object_unref (G_OBJECT (op->data.image.colorize_cache_pixbuf)); /* const cast here */ ((MetaDrawOp*)op)->data.image.colorize_cache_pixbuf = colorize_pixbuf (op->data.image.pixbuf, &color); ((MetaDrawOp*)op)->data.image.colorize_cache_pixel = GDK_COLOR_RGB (color); } if (op->data.image.colorize_cache_pixbuf) { pixbuf = scale_and_alpha_pixbuf (op->data.image.colorize_cache_pixbuf, op->data.image.alpha_spec, op->data.image.fill_type, width, height, op->data.image.vertical_stripes, op->data.image.horizontal_stripes); } } else { pixbuf = scale_and_alpha_pixbuf (op->data.image.pixbuf, op->data.image.alpha_spec, op->data.image.fill_type, width, height, op->data.image.vertical_stripes, op->data.image.horizontal_stripes); } break; } case META_DRAW_GTK_ARROW: case META_DRAW_GTK_BOX: case META_DRAW_GTK_VLINE: break; case META_DRAW_ICON: if (info->mini_icon && width <= gdk_pixbuf_get_width (info->mini_icon) && height <= gdk_pixbuf_get_height (info->mini_icon)) pixbuf = scale_and_alpha_pixbuf (info->mini_icon, op->data.icon.alpha_spec, op->data.icon.fill_type, width, height, FALSE, FALSE); else if (info->icon) pixbuf = scale_and_alpha_pixbuf (info->icon, op->data.icon.alpha_spec, op->data.icon.fill_type, width, height, FALSE, FALSE); break; case META_DRAW_TITLE: break; case META_DRAW_OP_LIST: break; case META_DRAW_TILE: break; } return pixbuf; } static void fill_env (MetaPositionExprEnv *env, const MetaDrawInfo *info, MetaRectangle logical_region) { /* FIXME this stuff could be raised into draw_op_list_draw() probably */ env->rect = logical_region; env->object_width = -1; env->object_height = -1; if (info->fgeom) { env->left_width = info->fgeom->borders.visible.left; env->right_width = info->fgeom->borders.visible.right; env->top_height = info->fgeom->borders.visible.top; env->bottom_height = info->fgeom->borders.visible.bottom; env->frame_x_center = info->fgeom->width / 2 - logical_region.x; env->frame_y_center = info->fgeom->height / 2 - logical_region.y; } else { env->left_width = 0; env->right_width = 0; env->top_height = 0; env->bottom_height = 0; env->frame_x_center = 0; env->frame_y_center = 0; } env->mini_icon_width = info->mini_icon ? gdk_pixbuf_get_width (info->mini_icon) : 0; env->mini_icon_height = info->mini_icon ? gdk_pixbuf_get_height (info->mini_icon) : 0; env->icon_width = info->icon ? gdk_pixbuf_get_width (info->icon) : 0; env->icon_height = info->icon ? gdk_pixbuf_get_height (info->icon) : 0; env->title_width = info->title_layout_width; env->title_height = info->title_layout_height; env->theme = meta_current_theme; } /* This code was originally rendering anti-aliased using X primitives, and * now has been switched to draw anti-aliased using cairo. In general, the * closest correspondence between X rendering and cairo rendering is given * by offsetting the geometry by 0.5 pixels in both directions before rendering * with cairo. This is because X samples at the upper left corner of the * pixel while cairo averages over the entire pixel. However, in the cases * where the X rendering was an exact rectangle with no "jaggies" * we need to be a bit careful about applying the offset. We want to produce * the exact same pixel-aligned rectangle, rather than a rectangle with * fuzz around the edges. */ static void meta_draw_op_draw_with_env (const MetaDrawOp *op, GtkStyleContext *style_gtk, GtkWidget *widget, cairo_t *cr, const MetaDrawInfo *info, MetaRectangle rect, MetaPositionExprEnv *env) { GdkRGBA color; cairo_save (cr); gtk_style_context_save (style_gtk); cairo_set_line_width (cr, 1.0); switch (op->type) { case META_DRAW_LINE: { int x1, x2, y1, y2; meta_color_spec_render (op->data.line.color_spec, style_gtk, &color); gdk_cairo_set_source_rgba (cr, &color); if (op->data.line.width > 0) cairo_set_line_width (cr, op->data.line.width); if (op->data.line.dash_on_length > 0 && op->data.line.dash_off_length > 0) { double dash_list[2]; dash_list[0] = op->data.line.dash_on_length; dash_list[1] = op->data.line.dash_off_length; cairo_set_dash (cr, dash_list, 2, 0); } x1 = parse_x_position_unchecked (op->data.line.x1, env); y1 = parse_y_position_unchecked (op->data.line.y1, env); if (!op->data.line.x2 && !op->data.line.y2 && op->data.line.width==0) { cairo_rectangle (cr, x1, y1, 1, 1); cairo_fill (cr); } else { if (op->data.line.x2) x2 = parse_x_position_unchecked (op->data.line.x2, env); else x2 = x1; if (op->data.line.y2) y2 = parse_y_position_unchecked (op->data.line.y2, env); else y2 = y1; /* This is one of the cases where we are matching the exact * pixel aligned rectangle produced by X; for zero-width lines * the generic algorithm produces the right result so we don't * need to handle them here. */ if ((y1 == y2 || x1 == x2) && op->data.line.width != 0) { double offset = op->data.line.width % 2 ? .5 : 0; if (y1 == y2) { cairo_move_to (cr, x1, y1 + offset); cairo_line_to (cr, x2, y2 + offset); } else { cairo_move_to (cr, x1 + offset, y1); cairo_line_to (cr, x2 + offset, y2); } } else { /* zero-width lines include both end-points in X, unlike wide lines */ if (op->data.line.width == 0) cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); cairo_move_to (cr, x1 + .5, y1 + .5); cairo_line_to (cr, x2 + .5, y2 + .5); } cairo_stroke (cr); } } break; case META_DRAW_RECTANGLE: { int rx, ry, rwidth, rheight; meta_color_spec_render (op->data.rectangle.color_spec, style_gtk, &color); gdk_cairo_set_source_rgba (cr, &color); rx = parse_x_position_unchecked (op->data.rectangle.x, env); ry = parse_y_position_unchecked (op->data.rectangle.y, env); rwidth = parse_size_unchecked (op->data.rectangle.width, env); rheight = parse_size_unchecked (op->data.rectangle.height, env); /* Filled and stroked rectangles are the other cases * we pixel-align to X rasterization */ if (op->data.rectangle.filled) { cairo_rectangle (cr, rx, ry, rwidth, rheight); cairo_fill (cr); } else { cairo_rectangle (cr, rx + .5, ry + .5, rwidth, rheight); cairo_stroke (cr); } } break; case META_DRAW_ARC: { int rx, ry, rwidth, rheight; double start_angle, end_angle; double center_x, center_y; meta_color_spec_render (op->data.arc.color_spec, style_gtk, &color); gdk_cairo_set_source_rgba (cr, &color); rx = parse_x_position_unchecked (op->data.arc.x, env); ry = parse_y_position_unchecked (op->data.arc.y, env); rwidth = parse_size_unchecked (op->data.arc.width, env); rheight = parse_size_unchecked (op->data.arc.height, env); start_angle = op->data.arc.start_angle * (M_PI / 180.) - (.5 * M_PI); /* start at 12 instead of 3 oclock */ end_angle = start_angle + op->data.arc.extent_angle * (M_PI / 180.); center_x = rx + (double)rwidth / 2. + .5; center_y = ry + (double)rheight / 2. + .5; cairo_save (cr); cairo_translate (cr, center_x, center_y); cairo_scale (cr, (double)rwidth / 2., (double)rheight / 2.); if (op->data.arc.extent_angle >= 0) cairo_arc (cr, 0, 0, 1, start_angle, end_angle); else cairo_arc_negative (cr, 0, 0, 1, start_angle, end_angle); cairo_restore (cr); if (op->data.arc.filled) { cairo_line_to (cr, center_x, center_y); cairo_fill (cr); } else cairo_stroke (cr); } break; case META_DRAW_CLIP: break; case META_DRAW_TINT: { int rx, ry, rwidth, rheight; gboolean needs_alpha; needs_alpha = op->data.tint.alpha_spec && (op->data.tint.alpha_spec->n_alphas > 1 || op->data.tint.alpha_spec->alphas[0] != 0xff); rx = parse_x_position_unchecked (op->data.tint.x, env); ry = parse_y_position_unchecked (op->data.tint.y, env); rwidth = parse_size_unchecked (op->data.tint.width, env); rheight = parse_size_unchecked (op->data.tint.height, env); if (!needs_alpha) { meta_color_spec_render (op->data.tint.color_spec, style_gtk, &color); gdk_cairo_set_source_rgba (cr, &color); cairo_rectangle (cr, rx, ry, rwidth, rheight); cairo_fill (cr); } else { GdkPixbuf *pixbuf; pixbuf = draw_op_as_pixbuf (op, style_gtk, info, rwidth, rheight); if (pixbuf) { gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry); cairo_paint (cr); g_object_unref (G_OBJECT (pixbuf)); } } } break; case META_DRAW_GRADIENT: { int rx, ry, rwidth, rheight; GdkPixbuf *pixbuf; rx = parse_x_position_unchecked (op->data.gradient.x, env); ry = parse_y_position_unchecked (op->data.gradient.y, env); rwidth = parse_size_unchecked (op->data.gradient.width, env); rheight = parse_size_unchecked (op->data.gradient.height, env); pixbuf = draw_op_as_pixbuf (op, style_gtk, info, rwidth, rheight); if (pixbuf) { gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry); cairo_paint (cr); g_object_unref (G_OBJECT (pixbuf)); } } break; case META_DRAW_IMAGE: { int rx, ry, rwidth, rheight; GdkPixbuf *pixbuf; if (op->data.image.pixbuf) { env->object_width = gdk_pixbuf_get_width (op->data.image.pixbuf); env->object_height = gdk_pixbuf_get_height (op->data.image.pixbuf); } rwidth = parse_size_unchecked (op->data.image.width, env); rheight = parse_size_unchecked (op->data.image.height, env); pixbuf = draw_op_as_pixbuf (op, style_gtk, info, rwidth, rheight); if (pixbuf) { rx = parse_x_position_unchecked (op->data.image.x, env); ry = parse_y_position_unchecked (op->data.image.y, env); gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry); cairo_paint (cr); g_object_unref (G_OBJECT (pixbuf)); } } break; case META_DRAW_GTK_ARROW: { int rx, ry, rwidth, rheight; double angle = 0, size; rx = parse_x_position_unchecked (op->data.gtk_arrow.x, env); ry = parse_y_position_unchecked (op->data.gtk_arrow.y, env); rwidth = parse_size_unchecked (op->data.gtk_arrow.width, env); rheight = parse_size_unchecked (op->data.gtk_arrow.height, env); size = MAX(rwidth, rheight); switch (op->data.gtk_arrow.arrow) { case GTK_ARROW_UP: angle = 0; break; case GTK_ARROW_RIGHT: angle = M_PI / 2; break; case GTK_ARROW_DOWN: angle = M_PI; break; case GTK_ARROW_LEFT: angle = 3 * M_PI / 2; break; case GTK_ARROW_NONE: return; } gtk_style_context_set_state (style_gtk, op->data.gtk_arrow.state); gtk_render_arrow (style_gtk, cr, angle, rx, ry, size); } break; case META_DRAW_GTK_BOX: { int rx, ry, rwidth, rheight; rx = parse_x_position_unchecked (op->data.gtk_box.x, env); ry = parse_y_position_unchecked (op->data.gtk_box.y, env); rwidth = parse_size_unchecked (op->data.gtk_box.width, env); rheight = parse_size_unchecked (op->data.gtk_box.height, env); gtk_style_context_set_state (style_gtk, op->data.gtk_box.state); gtk_render_background (style_gtk, cr, rx, ry, rwidth, rheight); gtk_render_frame (style_gtk, cr, rx, ry, rwidth, rheight); } break; case META_DRAW_GTK_VLINE: { int rx, ry1, ry2; rx = parse_x_position_unchecked (op->data.gtk_vline.x, env); ry1 = parse_y_position_unchecked (op->data.gtk_vline.y1, env); ry2 = parse_y_position_unchecked (op->data.gtk_vline.y2, env); gtk_style_context_set_state (style_gtk, op->data.gtk_vline.state); gtk_render_line (style_gtk, cr, rx, ry1, rx, ry2); } break; case META_DRAW_ICON: { int rx, ry, rwidth, rheight; GdkPixbuf *pixbuf; rwidth = parse_size_unchecked (op->data.icon.width, env); rheight = parse_size_unchecked (op->data.icon.height, env); pixbuf = draw_op_as_pixbuf (op, style_gtk, info, rwidth, rheight); if (pixbuf) { rx = parse_x_position_unchecked (op->data.icon.x, env); ry = parse_y_position_unchecked (op->data.icon.y, env); gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry); cairo_paint (cr); g_object_unref (G_OBJECT (pixbuf)); } } break; case META_DRAW_TITLE: if (info->title_layout) { int rx, ry; PangoRectangle ink_rect, logical_rect; meta_color_spec_render (op->data.title.color_spec, style_gtk, &color); gdk_cairo_set_source_rgba (cr, &color); rx = parse_x_position_unchecked (op->data.title.x, env); ry = parse_y_position_unchecked (op->data.title.y, env); if (op->data.title.ellipsize_width) { int ellipsize_width; int right_bearing; ellipsize_width = parse_x_position_unchecked (op->data.title.ellipsize_width, env); /* HACK: parse_x_position_unchecked adds in env->rect.x, subtract out again */ ellipsize_width -= env->rect.x; pango_layout_set_width (info->title_layout, -1); pango_layout_get_pixel_extents (info->title_layout, &ink_rect, &logical_rect); /* Pango's idea of ellipsization is with respect to the logical rect. * correct for this, by reducing the ellipsization width by the overflow * of the un-ellipsized text on the right... it's always the visual * right we want regardless of bidi, since since the X we pass in to * cairo_move_to() is always the left edge of the line. */ right_bearing = (ink_rect.x + ink_rect.width) - (logical_rect.x + logical_rect.width); right_bearing = MAX (right_bearing, 0); ellipsize_width -= right_bearing; ellipsize_width = MAX (ellipsize_width, 0); /* Only ellipsizing when necessary is a performance optimization - * pango_layout_set_width() will force a relayout if it isn't the * same as the current width of -1. */ if (ellipsize_width < logical_rect.width) pango_layout_set_width (info->title_layout, PANGO_SCALE * ellipsize_width); } cairo_move_to (cr, rx, ry); pango_cairo_show_layout (cr, info->title_layout); /* Remove any ellipsization we might have set; will short-circuit * if the width is already -1 */ pango_layout_set_width (info->title_layout, -1); } break; case META_DRAW_OP_LIST: { MetaRectangle d_rect; d_rect.x = parse_x_position_unchecked (op->data.op_list.x, env); d_rect.y = parse_y_position_unchecked (op->data.op_list.y, env); d_rect.width = parse_size_unchecked (op->data.op_list.width, env); d_rect.height = parse_size_unchecked (op->data.op_list.height, env); meta_draw_op_list_draw_with_style (op->data.op_list.op_list, style_gtk, widget, cr, info, d_rect); } break; case META_DRAW_TILE: { int rx, ry, rwidth, rheight; int tile_xoffset, tile_yoffset; MetaRectangle tile; rx = parse_x_position_unchecked (op->data.tile.x, env); ry = parse_y_position_unchecked (op->data.tile.y, env); rwidth = parse_size_unchecked (op->data.tile.width, env); rheight = parse_size_unchecked (op->data.tile.height, env); cairo_save (cr); cairo_rectangle (cr, rx, ry, rwidth, rheight); cairo_clip (cr); tile_xoffset = parse_x_position_unchecked (op->data.tile.tile_xoffset, env); tile_yoffset = parse_y_position_unchecked (op->data.tile.tile_yoffset, env); /* tile offset should not include x/y */ tile_xoffset -= rect.x; tile_yoffset -= rect.y; tile.width = parse_size_unchecked (op->data.tile.tile_width, env); tile.height = parse_size_unchecked (op->data.tile.tile_height, env); tile.x = rx - tile_xoffset; while (tile.x < (rx + rwidth)) { tile.y = ry - tile_yoffset; while (tile.y < (ry + rheight)) { meta_draw_op_list_draw_with_style (op->data.tile.op_list, style_gtk, widget, cr, info, tile); tile.y += tile.height; } tile.x += tile.width; } cairo_restore (cr); } break; } cairo_restore (cr); gtk_style_context_restore (style_gtk); } LOCAL_SYMBOL void meta_draw_op_draw_with_style (const MetaDrawOp *op, GtkStyleContext *style_gtk, GtkWidget *widget, cairo_t *cr, const MetaDrawInfo *info, MetaRectangle logical_region) { MetaPositionExprEnv env; fill_env (&env, info, logical_region); meta_draw_op_draw_with_env (op, style_gtk, widget, cr, info, logical_region, &env); } LOCAL_SYMBOL void meta_draw_op_draw (const MetaDrawOp *op, GtkWidget *widget, cairo_t *cr, const MetaDrawInfo *info, MetaRectangle logical_region) { meta_draw_op_draw_with_style (op, gtk_widget_get_style_context (widget), widget, cr, info, logical_region); } /** * meta_draw_op_list_new: (skip) * */ LOCAL_SYMBOL MetaDrawOpList* meta_draw_op_list_new (int n_preallocs) { MetaDrawOpList *op_list; g_return_val_if_fail (n_preallocs >= 0, NULL); op_list = g_new (MetaDrawOpList, 1); op_list->refcount = 1; op_list->n_allocated = n_preallocs; op_list->ops = g_new (MetaDrawOp*, op_list->n_allocated); op_list->n_ops = 0; return op_list; } LOCAL_SYMBOL void meta_draw_op_list_ref (MetaDrawOpList *op_list) { g_return_if_fail (op_list != NULL); op_list->refcount += 1; } LOCAL_SYMBOL void meta_draw_op_list_unref (MetaDrawOpList *op_list) { g_return_if_fail (op_list != NULL); g_return_if_fail (op_list->refcount > 0); op_list->refcount -= 1; if (op_list->refcount == 0) { int i; for (i = 0; i < op_list->n_ops; i++) meta_draw_op_free (op_list->ops[i]); g_free (op_list->ops); DEBUG_FILL_STRUCT (op_list); g_free (op_list); } } LOCAL_SYMBOL void meta_draw_op_list_draw_with_style (const MetaDrawOpList *op_list, GtkStyleContext *style_gtk, GtkWidget *widget, cairo_t *cr, const MetaDrawInfo *info, MetaRectangle rect) { int i; MetaPositionExprEnv env; if (op_list->n_ops == 0) return; fill_env (&env, info, rect); /* FIXME this can be optimized, potentially a lot, by * compressing multiple ops when possible. For example, * anything convertible to a pixbuf can be composited * client-side, and putting a color tint over a pixbuf * can be done without creating the solid-color pixbuf. * * To implement this my plan is to have the idea of a * compiled draw op (with the string expressions already * evaluated), we make an array of those, and then fold * adjacent items when possible. */ cairo_save (cr); for (i = 0; i < op_list->n_ops; i++) { MetaDrawOp *op = op_list->ops[i]; if (op->type == META_DRAW_CLIP) { cairo_restore (cr); cairo_rectangle (cr, parse_x_position_unchecked (op->data.clip.x, &env), parse_y_position_unchecked (op->data.clip.y, &env), parse_size_unchecked (op->data.clip.width, &env), parse_size_unchecked (op->data.clip.height, &env)); cairo_clip (cr); cairo_save (cr); } else if (gdk_cairo_get_clip_rectangle (cr, NULL)) { meta_draw_op_draw_with_env (op, style_gtk, widget, cr, info, rect, &env); } } cairo_restore (cr); } LOCAL_SYMBOL void meta_draw_op_list_draw (const MetaDrawOpList *op_list, GtkWidget *widget, cairo_t *cr, const MetaDrawInfo *info, MetaRectangle rect) { meta_draw_op_list_draw_with_style (op_list, gtk_widget_get_style_context (widget), widget, cr, info, rect); } LOCAL_SYMBOL void meta_draw_op_list_append (MetaDrawOpList *op_list, MetaDrawOp *op) { if (op_list->n_ops == op_list->n_allocated) { op_list->n_allocated *= 2; op_list->ops = g_renew (MetaDrawOp*, op_list->ops, op_list->n_allocated); } op_list->ops[op_list->n_ops] = op; op_list->n_ops += 1; } LOCAL_SYMBOL gboolean meta_draw_op_list_validate (MetaDrawOpList *op_list, GError **error) { g_return_val_if_fail (op_list != NULL, FALSE); /* empty lists are OK, nothing else to check really */ return TRUE; } /* This is not done in validate, since we wouldn't know the name * of the list to report the error. It might be nice to * store names inside the list sometime. */ LOCAL_SYMBOL gboolean meta_draw_op_list_contains (MetaDrawOpList *op_list, MetaDrawOpList *child) { int i; /* mmm, huge tree recursion */ for (i = 0; i < op_list->n_ops; i++) { if (op_list->ops[i]->type == META_DRAW_OP_LIST) { if (op_list->ops[i]->data.op_list.op_list == child) return TRUE; if (meta_draw_op_list_contains (op_list->ops[i]->data.op_list.op_list, child)) return TRUE; } else if (op_list->ops[i]->type == META_DRAW_TILE) { if (op_list->ops[i]->data.tile.op_list == child) return TRUE; if (meta_draw_op_list_contains (op_list->ops[i]->data.tile.op_list, child)) return TRUE; } } return FALSE; } /* * Constructor for a MetaFrameStyle. * * \param parent The parent style. Data not filled in here will be * looked for in the parent style, and in its parent * style, and so on. * * \return The newly-constructed style. */ LOCAL_SYMBOL MetaFrameStyle* meta_frame_style_new (MetaFrameStyle *parent) { MetaFrameStyle *style; style = g_new0 (MetaFrameStyle, 1); style->refcount = 1; /* Default alpha is fully opaque */ style->window_background_alpha = 255; style->parent = parent; if (parent) meta_frame_style_ref (parent); return style; } /* * Increases the reference count of a frame style. * If the style is NULL, this is a no-op. * * \param style The style. */ LOCAL_SYMBOL void meta_frame_style_ref (MetaFrameStyle *style) { g_return_if_fail (style != NULL); style->refcount += 1; } static void free_button_ops (MetaDrawOpList *op_lists[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST]) { int i, j; for (i = 0; i < META_BUTTON_TYPE_LAST; i++) for (j = 0; j < META_BUTTON_STATE_LAST; j++) if (op_lists[i][j]) meta_draw_op_list_unref (op_lists[i][j]); } LOCAL_SYMBOL void meta_frame_style_unref (MetaFrameStyle *style) { g_return_if_fail (style != NULL); g_return_if_fail (style->refcount > 0); style->refcount -= 1; if (style->refcount == 0) { int i; free_button_ops (style->buttons); for (i = 0; i < META_FRAME_PIECE_LAST; i++) if (style->pieces[i]) meta_draw_op_list_unref (style->pieces[i]); if (style->layout) meta_frame_layout_unref (style->layout); if (style->window_background_color) meta_color_spec_free (style->window_background_color); /* we hold a reference to any parent style */ if (style->parent) meta_frame_style_unref (style->parent); DEBUG_FILL_STRUCT (style); g_free (style); } } static MetaButtonState map_button_state (MetaButtonType button_type, const MetaFrameGeometry *fgeom, int middle_bg_offset, MetaButtonState button_states[META_BUTTON_TYPE_LAST]) { MetaButtonFunction function = META_BUTTON_FUNCTION_LAST; switch (button_type) { /* First hande functions, which map directly */ case META_BUTTON_TYPE_SHADE: case META_BUTTON_TYPE_ABOVE: case META_BUTTON_TYPE_STICK: case META_BUTTON_TYPE_UNSHADE: case META_BUTTON_TYPE_UNABOVE: case META_BUTTON_TYPE_UNSTICK: case META_BUTTON_TYPE_MENU: case META_BUTTON_TYPE_MINIMIZE: case META_BUTTON_TYPE_MAXIMIZE: case META_BUTTON_TYPE_CLOSE: return button_states[button_type]; /* Map position buttons to the corresponding function */ case META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND: case META_BUTTON_TYPE_RIGHT_SINGLE_BACKGROUND: if (fgeom->n_right_buttons > 0) function = fgeom->button_layout.right_buttons[0]; break; case META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND: if (fgeom->n_right_buttons > 0) function = fgeom->button_layout.right_buttons[fgeom->n_right_buttons - 1]; break; case META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND: if (middle_bg_offset + 1 < fgeom->n_right_buttons) function = fgeom->button_layout.right_buttons[middle_bg_offset + 1]; break; case META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND: case META_BUTTON_TYPE_LEFT_SINGLE_BACKGROUND: if (fgeom->n_left_buttons > 0) function = fgeom->button_layout.left_buttons[0]; break; case META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND: if (fgeom->n_left_buttons > 0) function = fgeom->button_layout.left_buttons[fgeom->n_left_buttons - 1]; break; case META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND: if (middle_bg_offset + 1 < fgeom->n_left_buttons) function = fgeom->button_layout.left_buttons[middle_bg_offset + 1]; break; case META_BUTTON_TYPE_LAST: break; } if (function != META_BUTTON_FUNCTION_LAST) return button_states[map_button_function_to_type (function)]; return META_BUTTON_STATE_LAST; } static MetaDrawOpList* get_button (MetaFrameStyle *style, MetaButtonType type, MetaButtonState state) { MetaDrawOpList *op_list; MetaFrameStyle *parent; parent = style; op_list = NULL; while (parent && op_list == NULL) { op_list = parent->buttons[type][state]; parent = parent->parent; } /* We fall back to the side buttons if we don't have * single button backgrounds, and to middle button * backgrounds if we don't have the ones on the sides */ if (op_list == NULL && type == META_BUTTON_TYPE_LEFT_SINGLE_BACKGROUND) return get_button (style, META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND, state); if (op_list == NULL && type == META_BUTTON_TYPE_RIGHT_SINGLE_BACKGROUND) return get_button (style, META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND, state); if (op_list == NULL && (type == META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND || type == META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND)) return get_button (style, META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND, state); if (op_list == NULL && (type == META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND || type == META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND)) return get_button (style, META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND, state); /* We fall back to normal if no prelight */ if (op_list == NULL && state == META_BUTTON_STATE_PRELIGHT) return get_button (style, type, META_BUTTON_STATE_NORMAL); return op_list; } LOCAL_SYMBOL gboolean meta_frame_style_validate (MetaFrameStyle *style, guint current_theme_version, GError **error) { int i, j; g_return_val_if_fail (style != NULL, FALSE); g_return_val_if_fail (style->layout != NULL, FALSE); for (i = 0; i < META_BUTTON_TYPE_LAST; i++) { /* for now the "positional" buttons are optional */ if (i >= META_BUTTON_TYPE_CLOSE) { for (j = 0; j < META_BUTTON_STATE_LAST; j++) { if (get_button (style, i, j) == NULL && meta_theme_earliest_version_with_button (i) <= current_theme_version ) { g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED, _("