├── .gitignore ├── AUTHORS ├── COPYING ├── HISTORY ├── LICENSE ├── Makefile.am ├── README.md ├── autogen.sh ├── configure.ac ├── docs └── reference │ ├── Makefile.am │ ├── statusnotifier-docs.xml │ ├── statusnotifier-sections.txt │ ├── statusnotifier.types │ └── version.xml.in ├── example ├── Makefile.am └── sn-example.c ├── m4 ├── cflagsadd.m4 └── introspection.m4 ├── src ├── closures ├── closures.c ├── closures.def ├── closures.h ├── enums.c.template ├── enums.h.template ├── interfaces.h ├── mkenums ├── statusnotifier-compat.h ├── statusnotifier.c └── statusnotifier.h └── statusnotifier.pc.in /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.bak 3 | *.o 4 | *.lo 5 | *.orig 6 | *.rej 7 | .dirstamp 8 | .deps/ 9 | .libs/ 10 | build-aux/ 11 | docs/reference/html 12 | docs/reference/html-build.stamp 13 | docs/reference/html.stamp 14 | docs/reference/sgml-build.stamp 15 | docs/reference/sgml.stamp 16 | docs/reference/scan-build.stamp 17 | docs/reference/setup-build.stamp 18 | docs/reference/xml 19 | docs/reference/version.xml 20 | docs/reference/statusnotifier.args 21 | docs/reference/statusnotifier-decl-list.txt 22 | docs/reference/statusnotifier-decl.txt 23 | docs/reference/statusnotifier.hierarchy 24 | docs/reference/statusnotifier.interfaces 25 | docs/reference/statusnotifier.prerequisites 26 | docs/reference/statusnotifier.signals 27 | docs/reference/statusnotifier-undeclared.txt 28 | docs/reference/statusnotifier-undocumented.txt 29 | docs/reference/statusnotifier-unused.txt 30 | Makefile 31 | Makefile.in 32 | aclocal.m4 33 | autogen.log 34 | autom4te.cache/ 35 | m4/gtk-doc.m4 36 | m4/libtool.m4 37 | m4/ltoptions.m4 38 | m4/ltsugar.m4 39 | m4/lt~obsolete.m4 40 | m4/ltversion.m4 41 | /gtk-doc.make 42 | /compile 43 | /config.h 44 | /config.h.in 45 | /config.log 46 | /config.status 47 | /configure 48 | /libtool 49 | /libstatusnotifier.la 50 | /statusnotifier.pc 51 | /example/sn-example 52 | stamp-h1 53 | src/enums.h 54 | src/enums.c 55 | StatusNotifier-*.gir 56 | StatusNotifier-*.typelib 57 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | statusnotifier is developed by Olivier Brunel 2 | See LICENSE for more 3 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /HISTORY: -------------------------------------------------------------------------------- 1 | 2 | # 2017-03-10, v1.0.0 3 | 4 | With contributions from Bradley Xu and Vladimir Perepechin. 5 | 6 | !!! Renaming of StatusNotifier to StatusNotifierItem, and all functions from 7 | status_notifier_XXX to status_notifier_item_XXX 8 | 9 | Yes, this breaks things. It's unfortunate, but we didn't really follow the 10 | GObject convention for naming things, and as a result it made things a bit 11 | awkward/complicated when it comes to introspection, and bindings to use 12 | statusnotifier from other languages (e.g. Perl). 13 | 14 | There was no other changes, only typedef/functions/macros renamed, so fixing 15 | code written for previous version is only a matter or search&replace. 16 | 17 | Note that a statusnotifier-compat.h is provided, that defines a bunch of 18 | macros and should allow old code to keep working without any changes 19 | required, only this extra include. As a transitional aid of sorts. 20 | 21 | +++ Add optional dbusmenu support via libdbusmenu 22 | 23 | +++ Add optional generation of introspection data. Thanks to Frédéric Buclin for 24 | his help. 25 | 26 | + Update to newer specs; Add item-is-menu 27 | 28 | ! Fix possibly using wrong scroll orientation 29 | 30 | ! Fix getting/setting property window-id 31 | 32 | * Other fixes/cleanups; see git log for details 33 | 34 | 35 | # 2014-06-08, v0.1.0 36 | 37 | * first release 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | statusnotifier is released under the GNU General Public License v3+ 2 | Copyright (C) 2014-2017 Olivier Brunel 3 | See COPYING 4 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | CLEANFILES = 3 | 4 | SUBDIRS = . docs/reference 5 | if EXAMPLE 6 | SUBDIRS += example 7 | endif 8 | 9 | ACLOCAL_AMFLAGS = -I m4 10 | 11 | if USE_GIT_VERSION 12 | _VERSION = `git describe --abbrev=4 --dirty` 13 | DEFS += -DGIT_VERSION=\"$(_VERSION)\" 14 | else 15 | _VERSION = $(PACKAGE_VERSION) 16 | endif 17 | 18 | AM_CFLAGS = \ 19 | -g \ 20 | -DDOCDIR='"$(docdir)"' \ 21 | ${WARNING_CFLAGS} 22 | 23 | lib_LTLIBRARIES = libstatusnotifier.la 24 | include_HEADERS = src/statusnotifier.h src/statusnotifier-compat.h 25 | 26 | pkgconfigdir = $(libdir)/pkgconfig 27 | pkgconfig_DATA = statusnotifier.pc 28 | 29 | libstatusnotifier_la_LDFLAGS = -version-info $(LIB_VERSION_INFO) 30 | libstatusnotifier_la_CFLAGS = ${AM_CFLAGS} @DEP_CFLAGS@ 31 | libstatusnotifier_la_LIBADD = @DEP_LIBS@ 32 | libstatusnotifier_la_SOURCES = \ 33 | src/enums.h \ 34 | src/enums.c \ 35 | src/statusnotifier.h \ 36 | src/statusnotifier.c \ 37 | src/closures.h \ 38 | src/closures.c \ 39 | src/interfaces.h 40 | 41 | EXTRA_DIST = \ 42 | src/closures \ 43 | src/closures.def \ 44 | src/mkenums \ 45 | m4/introspection.m4 46 | 47 | src/enums.h: src/statusnotifier.h 48 | $(AM_V_GEN) cd $(top_srcdir)/src && ./mkenums 49 | 50 | src/enums.c: src/statusnotifier.h 51 | $(AM_V_GEN) cd $(top_srcdir)/src && ./mkenums 52 | 53 | 54 | if HAVE_INTROSPECTION 55 | BUILT_GIRSOURCES = StatusNotifier-$(GIR_VERSION).gir 56 | 57 | GIR_EXTRA = 58 | if USE_DBUSMENU 59 | GIR_EXTRA += -DUSE_DBUSMENU=1 --include=Gtk-3.0 60 | endif 61 | StatusNotifier-$(GIR_VERSION).gir: $(INTROSPECTION_SCANNER) libstatusnotifier.la 62 | $(AM_V_GEN) $(INTROSPECTION_SCANNER) \ 63 | -v --warn-all -n StatusNotifier --nsversion=$(GIR_VERSION) \ 64 | --include=GObject-2.0 --include=GdkPixbuf-2.0 \ 65 | $(INCLUDES) $(GIR_EXTRA) \ 66 | --library=statusnotifier -o $@ \ 67 | src/statusnotifier.[ch] src/enums.[ch] 68 | 69 | girdir = $(datadir)/gir-1.0 70 | gir_DATA = $(BUILT_GIRSOURCES) 71 | 72 | typelibsdir = $(libdir)/girepository-1.0 73 | typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) 74 | 75 | %.typelib: %.gir $(INTROSPECTION_COMPILER) 76 | $(AM_V_GEN) $(INTROSPECTION_COMPILER) \ 77 | --includedir=$(srcdir) --includedir=. $(INTROSPECTION_COMPILER_OPTS) \ 78 | $< -o $(@F) 79 | 80 | CLEANFILES += $(BUILT_GIRSOURCES) $(typelibs_DATA) 81 | endif 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # statusnotifier: GObject Status Notifier Item 3 | 4 | Starting with Plasma Next, KDE doesn't support the XEmbed systray in favor of 5 | their own Status Notifier Specification. 6 | 7 | This little library allows to easily create a GObject to manage a 8 | StatusNotifierItem, handling all the DBus interface and letting you simply deal 9 | with the object's properties and signals. 10 | 11 | You can simply create a new StatusNotifier using one of the helper function, 12 | e.g. `status_notifier_item_new_from_icon_name()`, or simply creating an object 13 | as usual - you then just need to make sure to specify property `id` : 14 | 15 | sn = (StatusNotifier *) g_object_new (STATUS_NOTIFIER_TYPE_ITEM, 16 | "id", "app-id", 17 | "status", STATUS_NOTIFIER_STATUS_NEEDS_ATTENTION, 18 | "main-icon-name", "app-icon", 19 | "attention-icon-pixbuf", pixbuf, 20 | "tooltip-title", "My tooltip", 21 | "tooltip-body", "This is an item about app", 22 | NULL); 23 | 24 | You can also set properties (other than `id`) after creation. Once ready, call 25 | `status_notifier_item_register()` to register the item on the session bus and to 26 | the StatusNotifierWatcher. 27 | 28 | If an error occurs, signal `registration-failed` will be emitted. On success, 29 | property `state` will be `STATUS_NOTIFIER_STATE_REGISTERED`. 30 | 31 | Once registered, you can change properties as needed, and the proper DBus 32 | signal will be emitted to let visualizations (hosts) know, and connect to the 33 | signals (such as `context-menu`) which will be emitted when the corresponding 34 | DBus method was called. 35 | 36 | Simple as that. 37 | 38 | ## Free Software 39 | 40 | statusnotifier - Copyright (C) 2014-2017 Olivier Brunel 41 | 42 | statusnotifier is free software: you can redistribute it and/or modify it under 43 | the terms of the GNU General Public License as published by the Free Software 44 | Foundation, either version 3 of the License, or (at your option) any later 45 | version. 46 | 47 | statusnotifier is distributed in the hope that it will be useful, but WITHOUT 48 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 49 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 50 | 51 | You should have received a copy of the GNU General Public License along with 52 | statusnotifier (COPYING). If not, see http://www.gnu.org/licenses/ 53 | 54 | ## Want to know more? 55 | 56 | Some useful links if you're looking for more info: 57 | 58 | - [official site](https://jjacky.com/statusnotifier "statusnotifier @ jjacky.com") 59 | 60 | - [source code & issue tracker](https://github.com/jjk-jacky/statusnotifier "statusnotifier @ GitHub.com") 61 | 62 | - [PKGBUILD in AUR](https://aur.archlinux.org/packages/statusnotifier "AUR: statusnotifier") 63 | 64 | Plus, statusnotifier comes with html documentation. 65 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # statusnotifier - Copyright (C) 2014-2017 Olivier Brunel 4 | # 5 | # autogen.sh 6 | # Copyright (C) 2014 Olivier Brunel 7 | # Copyright (C) 2003-2012 Sebastien Helleu 8 | # Copyright (C) 2005 Julien Louis 9 | # Copyright (C) 2005-2006 Emmanuel Bouthenot 10 | # 11 | # This file is part of statusnotifier 12 | # 13 | # statusnotifier is free software: you can redistribute it and/or modify it 14 | # under the terms of the GNU General Public License as published by the Free 15 | # Software Foundation, either version 3 of the License, or (at your option) any 16 | # later version. 17 | # 18 | # statusnotifier is distributed in the hope that it will be useful, but WITHOUT 19 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 20 | # FOR A PARTICULAR PURPOSE. 21 | # See the GNU General Public License for more details. 22 | # 23 | # You should have received a copy of the GNU General Public License along with 24 | # statusnotifier If not, see http://www.gnu.org/licenses/ 25 | 26 | # Based on autogen.sh from WeeChat, http://weechat.org 27 | 28 | LOG=autogen.log 29 | 30 | abort() 31 | { 32 | echo "An error occured, the output below can be found in $LOG" 33 | echo "-------" 34 | cat $LOG 35 | exit 1 36 | } 37 | 38 | run() 39 | { 40 | echo -n "Running \"$@\" ... " 41 | echo "$ $@" >>$LOG 42 | eval $@ >>$LOG 2>&1 43 | if [ $? -eq 0 ]; then 44 | echo "OK" 45 | else 46 | echo "FAILED" 47 | abort 48 | fi 49 | } 50 | 51 | if [ -e $LOG ]; then 52 | rm "$LOG" 53 | fi 54 | 55 | #run "autopoint" 56 | run "gtkdocize" 57 | run "libtoolize --automake --copy" 58 | run "aclocal -I m4" 59 | run "autoheader" 60 | run "autoconf" 61 | run "automake --add-missing --copy" 62 | 63 | echo "done; Full log available in $LOG" 64 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | # package version 5 | m4_define([pkg_version], [1.0.0]) 6 | # REMEMBER to replace all @NEXT_VERSION@ by the new version number if needed 7 | # (used for doc, in Since: mostly). 8 | 9 | # library version 10 | # 11 | # current The most recent interface number that this library implements. 12 | # revision The implementation number of the current interface. 13 | # age The difference between the newest and oldest interfaces that this 14 | # library implements. In other words, the library implements all the 15 | # interface numbers in the range from number current - age to current 16 | # 17 | # 1. Start with version information of ‘0:0:0’ for each libtool library. 18 | # 2. Update the version information only immediately before a public release of 19 | # your software. More frequent updates are unnecessary, and only guarantee 20 | # that the current interface number gets larger faster. 21 | # 3. If the library source code has changed at all since the last update, then 22 | # increment revision (‘c:r:a’ becomes ‘c:r+1:a’). 23 | # 4. If any interfaces have been added, removed, or changed since the last 24 | # update, increment current, and set revision to 0. 25 | # 5. If any interfaces have been added since the last public release, then 26 | # increment age. 27 | # 6. If any interfaces have been removed or changed since the last public 28 | # release, then set age to 0. 29 | m4_define([lib_current], [1]) 30 | m4_define([lib_revision], [0]) 31 | m4_define([lib_age], [0]) 32 | 33 | # GIR namespace version 34 | m4_define([gir_version], [1.0]) 35 | 36 | 37 | AC_PREREQ([2.69]) 38 | AC_INIT([statusnotifier], [pkg_version], [jjk@jjacky.com]) 39 | AC_CONFIG_SRCDIR([src/statusnotifier.c]) 40 | AC_CONFIG_HEADERS([config.h]) 41 | AC_CONFIG_MACRO_DIR([m4]) 42 | AC_CONFIG_AUX_DIR([build-aux]) 43 | 44 | AM_INIT_AUTOMAKE([-Wall -Werror -Wno-portability foreign silent-rules subdir-objects]) 45 | AM_SILENT_RULES([yes]) 46 | 47 | # Option to make doc 48 | m4_ifdef([GTK_DOC_CHECK], [ 49 | GTK_DOC_CHECK([1.19],[--flavour no-tmpl]) 50 | AC_PATH_PROG([XSLTPROC], [xsltproc]) 51 | if test -z "$XSLTPROC"; then 52 | if test "$enable_man" = yes ; then 53 | AC_MSG_ERROR([xsltproc is required for --enable-gtk-doc]) 54 | fi 55 | fi 56 | ],[ 57 | AM_CONDITIONAL([ENABLE_GTK_DOC], false) 58 | ]) 59 | 60 | # Checks for programs. 61 | AC_PROG_CC 62 | AM_PROG_AR 63 | 64 | LT_INIT 65 | LIB_VERSION_INFO="lib_current:lib_revision:lib_age" 66 | AC_SUBST(LIB_VERSION_INFO) 67 | 68 | GIR_VERSION="gir_version" 69 | AC_SUBST(GIR_VERSION) 70 | 71 | # Option for example 72 | AC_ARG_ENABLE([example], 73 | AS_HELP_STRING([--enable-example], [enable the example]), 74 | [wantexample=$enableval], [wantexample=no]) 75 | 76 | # Option to use git version 77 | AC_ARG_ENABLE([git-version], 78 | AS_HELP_STRING([--enable-git-version], [enable the use of git version]), 79 | [wantgitver=$enableval], [wantgitver=no]) 80 | 81 | # Enable extra compiler warning flags 82 | AC_ARG_ENABLE([warning-flags], 83 | AS_HELP_STRING([--enable-warning-flags], [enable extra compiler warning flags]), 84 | [warningflags=$enableval], [warningflags=no]) 85 | 86 | AC_ARG_ENABLE([dbusmenu], 87 | AS_HELP_STRING([--enable-dbusmenu], [enable extra dbusmenu functionality via libdbusmenu]), 88 | [dbusmenu=$enableval], [dbusmenu=no]) 89 | 90 | # Checks for libraries. 91 | PKG_CHECK_MODULES(GOBJECT, [gobject-2.0], , AC_MSG_ERROR([GLib/GObject is required])) 92 | PKG_CHECK_MODULES(GIO, [gio-2.0], , AC_MSG_ERROR([GLib/GIO is required])) 93 | PKG_CHECK_MODULES(GDK, [gdk-3.0], , AC_MSG_ERROR([GDK 3 is required])) 94 | PKG_CHECK_MODULES(GDK_PIXBUF, [gdk-pixbuf-2.0], , AC_MSG_ERROR([gdk-pixbuf is required])) 95 | if test "x$wantexample" = "xyes"; then 96 | PKG_CHECK_MODULES(GTK, [gtk+-3.0], 97 | AC_DEFINE([EXAMPLE], , [Enable example]), 98 | AC_MSG_ERROR([GTK+3 is required for the example])) 99 | else 100 | enable_example=no 101 | fi 102 | AM_CONDITIONAL(EXAMPLE, test "x$wantexample" = "xyes") 103 | 104 | DEP_PACKAGES="gobject-2.0 gio-2.0 gdk-3.0 gdk-pixbuf-2.0" 105 | DEP_CFLAGS="$GOBJECT_CFLAGS $GIO_CFLAGS $GDK_CFLAGS $GDK_PIXBUF_CFLAGS" 106 | DEP_LIBS="$GOBJECT_LIBS $GIO_LIBS $GDK_LIBS $GDK_PIXBUF_LIBS" 107 | 108 | # dbusmenu support 109 | if test "x$dbusmenu" = "xyes"; then 110 | # we require GTK to deal with GtkWidget-s (menu to export) 111 | PKG_CHECK_MODULES(GTK, [gtk+-3.0], , 112 | AC_MSG_ERROR([GTK+3 is required for dbusmenu support])) 113 | DEP_PACKAGES="$DEP_PACKAGES gtk+-3.0" 114 | DEP_CFLAGS="$DEP_CFLAGS $GTK_CFLAGS" 115 | DEP_LIBS="$DEP_LIBS $GTK_LIBS" 116 | 117 | PKG_CHECK_MODULES(DBUSMENU, [dbusmenu-glib-0.4 dbusmenu-gtk3-0.4], , 118 | AC_MSG_ERROR([dbusmenu-glib and dbusmenu-gtk3 are required for dbusmenu support]) 119 | ]) 120 | DEP_PACKAGES="$DEP_PACKAGES dbusmenu-glib-0.4 dbusmenu-gtk3-0.4" 121 | DEP_CFLAGS="$DEP_CFLAGS $DBUSMENU_CFLAGS" 122 | DEP_LIBS="$DEP_LIBS $DBUSMENU_LIBS" 123 | 124 | AC_DEFINE([USE_DBUSMENU], 1, [Use dbusmenu]) 125 | dbusmenu=yes 126 | else 127 | dbusmenu=no 128 | fi 129 | AM_CONDITIONAL(USE_DBUSMENU, test "x$dbusmenu" = "xyes") 130 | 131 | # introspection 132 | GOBJECT_INTROSPECTION_CHECK([0.6.3]) 133 | 134 | AC_SUBST(DEP_PACKAGES) 135 | AC_SUBST(DEP_CFLAGS) 136 | AC_SUBST(DEP_LIBS) 137 | 138 | # Checks for header files. 139 | AC_CHECK_HEADERS([unistd.h]) 140 | 141 | # Checks for typedefs, structures, and compiler characteristics. 142 | 143 | # Checks for library functions. 144 | 145 | # git version 146 | AC_MSG_CHECKING([if git version must be used]) 147 | if test "x$wantgitver" = "xyes"; then 148 | AC_MSG_RESULT([yes]) 149 | AC_CHECK_PROGS([GIT], [git]) 150 | if test "x$GIT" = "x"; then 151 | AC_MSG_ERROR([Cannot use git version: git not found]) 152 | fi 153 | AC_CHECK_FILE([.git/], hasgitdir=yes) 154 | if test "x$hasgitdir" = "xyes"; then 155 | usegitver=yes 156 | gitver=-git 157 | AC_DEFINE([USE_GIT_VERSION], , [Use GIT version]) 158 | else 159 | AC_MSG_ERROR([Cannot use git version: .git not found]) 160 | fi 161 | else 162 | AC_MSG_RESULT([no]) 163 | usegitver=no 164 | gitver= 165 | fi 166 | AM_CONDITIONAL(USE_GIT_VERSION, test "x$usegitver" = "xyes") 167 | 168 | # warning flags 169 | WARNING_CFLAGS="-Wall" 170 | AC_MSG_CHECKING([for extra compiler warning flags]) 171 | if test "x$warningflags" = "xyes"; then 172 | AC_MSG_RESULT([yes]) 173 | CFLAGS_ADD([-Wextra], [WARNING_CFLAGS]) 174 | CFLAGS_ADD([-Wshadow], [WARNING_CFLAGS]) 175 | CFLAGS_ADD([-Wpointer-arith], [WARNING_CFLAGS]) 176 | CFLAGS_ADD([-Wcast-align], [WARNING_CFLAGS]) 177 | CFLAGS_ADD([-Wwrite-strings], [WARNING_CFLAGS]) 178 | CFLAGS_ADD([-Wmissing-prototypes], [WARNING_CFLAGS]) 179 | CFLAGS_ADD([-Wmissing-declarations], [WARNING_CFLAGS]) 180 | CFLAGS_ADD([-Wredundant-decls], [WARNING_CFLAGS]) 181 | CFLAGS_ADD([-Wnested-externs], [WARNING_CFLAGS]) 182 | CFLAGS_ADD([-Winline], [WARNING_CFLAGS]) 183 | CFLAGS_ADD([-Wno-long-long], [WARNING_CFLAGS]) 184 | CFLAGS_ADD([-Wuninitialized], [WARNING_CFLAGS]) 185 | CFLAGS_ADD([-Wconversion], [WARNING_CFLAGS]) 186 | CFLAGS_ADD([-Wstrict-prototypes], [WARNING_CFLAGS]) 187 | 188 | CFLAGS_ADD([-Wclobbered], [WARNING_CFLAGS]) 189 | CFLAGS_ADD([-Wempty-body], [WARNING_CFLAGS]) 190 | CFLAGS_ADD([-Wfloat-equal], [WARNING_CFLAGS]) 191 | CFLAGS_ADD([-Wformat-nonliteral], [WARNING_CFLAGS]) 192 | CFLAGS_ADD([-Wformat-security], [WARNING_CFLAGS]) 193 | CFLAGS_ADD([-Wignored-qualifiers], [WARNING_CFLAGS]) 194 | CFLAGS_ADD([-Wlogical-op], [WARNING_CFLAGS]) 195 | CFLAGS_ADD([-Wmissing-field-initializers], [WARNING_CFLAGS]) 196 | CFLAGS_ADD([-Wmissing-parameter-type], [WARNING_CFLAGS]) 197 | CFLAGS_ADD([-Wold-style-declaration], [WARNING_CFLAGS]) 198 | CFLAGS_ADD([-Woverride-init], [WARNING_CFLAGS]) 199 | CFLAGS_ADD([-Wsign-compare], [WARNING_CFLAGS]) 200 | CFLAGS_ADD([-Wstrict-aliasing], [WARNING_CFLAGS]) 201 | CFLAGS_ADD([-Wstrict-overflow=5], [WARNING_CFLAGS]) 202 | CFLAGS_ADD([-Wtype-limits], [WARNING_CFLAGS]) 203 | CFLAGS_ADD([-Wunused-but-set-parameter], [WARNING_CFLAGS]) 204 | CFLAGS_ADD([-Wunused-parameter], [WARNING_CFLAGS]) 205 | else 206 | AC_MSG_RESULT([no]) 207 | fi 208 | 209 | AC_CONFIG_FILES([Makefile statusnotifier.pc example/Makefile 210 | docs/reference/Makefile docs/reference/version.xml]) 211 | AC_OUTPUT 212 | echo " 213 | ${PACKAGE} version ${PACKAGE_VERSION}${gitver} 214 | 215 | Build information: 216 | source code location : ${srcdir} 217 | prefix : ${prefix} 218 | compiler warning flags : ${WARNING_CFLAGS} 219 | 220 | build html documentation : ${enable_gtk_doc} 221 | example : ${enable_example} 222 | dbusmenu : ${dbusmenu} 223 | introspection : ${enable_introspection} 224 | 225 | Install paths: 226 | binaries : $(eval echo $(eval echo ${bindir})) 227 | libraries : $(eval echo $(eval echo ${libdir})) 228 | documentation : $(eval echo $(eval echo ${docdir})) 229 | man pages : $(eval echo $(eval echo ${mandir})) 230 | " 231 | 232 | -------------------------------------------------------------------------------- /docs/reference/Makefile.am: -------------------------------------------------------------------------------- 1 | ## Process this file with automake to produce Makefile.in 2 | 3 | # We require automake 1.6 at least. 4 | AUTOMAKE_OPTIONS = 1.6 5 | 6 | # The name of the module, e.g. 'glib'. 7 | DOC_MODULE=statusnotifier 8 | 9 | # The top-level XML file (SGML in the past). You can change this if you want to. 10 | DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.xml 11 | 12 | # Directories containing the source code. 13 | # gtk-doc will search all .c and .h files beneath these paths 14 | # for inline comments documenting functions and macros. 15 | # e.g. DOC_SOURCE_DIR=$(top_srcdir)/gtk $(top_srcdir)/gdk 16 | DOC_SOURCE_DIR=$(top_srcdir)/src 17 | 18 | # Extra options to pass to gtkdoc-scangobj. Not normally needed. 19 | SCANGOBJ_OPTIONS= 20 | 21 | # Extra options to supply to gtkdoc-scan. 22 | # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" 23 | SCAN_OPTIONS= 24 | 25 | # Extra options to supply to gtkdoc-mkdb. 26 | # e.g. MKDB_OPTIONS=--xml-mode --output-format=xml 27 | MKDB_OPTIONS=--xml-mode --output-format=xml --name-space=status_notifier_item 28 | 29 | # Extra options to supply to gtkdoc-mktmpl 30 | # e.g. MKTMPL_OPTIONS=--only-section-tmpl 31 | MKTMPL_OPTIONS= 32 | 33 | # Extra options to supply to gtkdoc-mkhtml 34 | MKHTML_OPTIONS= 35 | 36 | # Extra options to supply to gtkdoc-fixref. Not normally needed. 37 | # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html 38 | FIXXREF_OPTIONS= 39 | 40 | # Used for dependencies. The docs will be rebuilt if any of these change. 41 | # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h 42 | # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c 43 | HFILE_GLOB=$(top_srcdir)/src/*.h 44 | CFILE_GLOB=$(top_srcdir)/src/*.c 45 | 46 | # Extra header to include when scanning, which are not under DOC_SOURCE_DIR 47 | # e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h 48 | EXTRA_HFILES= 49 | 50 | # Header files or dirs to ignore when scanning. Use base file/dir names 51 | # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code 52 | IGNORE_HFILES=statusnotifier-compat.h 53 | 54 | # Images to copy into HTML directory. 55 | # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png 56 | HTML_IMAGES= 57 | 58 | # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). 59 | # e.g. content_files=running.sgml building.sgml changes-2.0.sgml 60 | content_files=version.xml 61 | 62 | # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded 63 | # These files must be listed here *and* in content_files 64 | # e.g. expand_content_files=running.sgml 65 | expand_content_files= 66 | 67 | # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. 68 | # Only needed if you are using gtkdoc-scangobj to dynamically query widget 69 | # signals and properties. 70 | # e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) 71 | # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) 72 | GTKDOC_CFLAGS=$(DEP_CFLAGS) 73 | GTKDOC_LIBS=$(DEP_LIBS) $(top_builddir)/.libs/libstatusnotifier.a 74 | 75 | # This includes the standard gtk-doc make rules, copied by gtkdocize. 76 | include $(top_srcdir)/gtk-doc.make 77 | 78 | # Other files to distribute 79 | # e.g. EXTRA_DIST += version.xml.in 80 | EXTRA_DIST += version.xml.in 81 | 82 | # Files not to distribute 83 | # for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types 84 | # for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt 85 | #DISTCLEANFILES += 86 | 87 | # Comment this out if you want 'make check' to test you doc status 88 | # and run some sanity checks 89 | if ENABLE_GTK_DOC 90 | TESTS_ENVIRONMENT = \ 91 | DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \ 92 | SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir) 93 | #TESTS = $(GTKDOC_CHECK) 94 | endif 95 | 96 | -include $(top_srcdir)/git.mk 97 | -------------------------------------------------------------------------------- /docs/reference/statusnotifier-docs.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | ]> 8 | 9 | 10 | statusnotifier Reference Manual 11 | 12 | for statusnotifier &version; 13 | 14 | 15 | 16 | 17 | Status Notifier Library 18 | 19 | 20 | 21 | 22 | Object Hierarchy 23 | 24 | 25 | 26 | Index of all symbols 27 | 28 | 29 | 30 | Index of new symbols in 1.0.0 31 | 32 | 33 | 34 | Index of deprecated API 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /docs/reference/statusnotifier-sections.txt: -------------------------------------------------------------------------------- 1 |
2 | statusnotifier 3 | StatusNotifier 4 | STATUS_NOTIFIER_ERROR 5 | StatusNotifierError 6 | StatusNotifierState 7 | StatusNotifierIcon 8 | StatusNotifierCategory 9 | StatusNotifierStatus 10 | StatusNotifierScrollOrientation 11 | StatusNotifierItem 12 | StatusNotifierItemClass 13 | status_notifier_item_new_from_pixbuf 14 | status_notifier_item_new_from_icon_name 15 | status_notifier_item_get_id 16 | status_notifier_item_get_category 17 | status_notifier_item_set_from_pixbuf 18 | status_notifier_item_set_from_icon_name 19 | status_notifier_item_has_pixbuf 20 | status_notifier_item_get_pixbuf 21 | status_notifier_item_get_icon_name 22 | status_notifier_item_set_attention_movie_name 23 | status_notifier_item_get_attention_movie_name 24 | status_notifier_item_set_title 25 | status_notifier_item_get_title 26 | status_notifier_item_set_status 27 | status_notifier_item_get_status 28 | status_notifier_item_set_window_id 29 | status_notifier_item_get_window_id 30 | status_notifier_item_freeze_tooltip 31 | status_notifier_item_thaw_tooltip 32 | status_notifier_item_set_tooltip 33 | status_notifier_item_set_tooltip_title 34 | status_notifier_item_get_tooltip_title 35 | status_notifier_item_set_tooltip_body 36 | status_notifier_item_get_tooltip_body 37 | status_notifier_item_set_item_is_menu 38 | status_notifier_item_get_item_is_menu 39 | status_notifier_item_set_context_menu 40 | status_notifier_item_get_context_menu 41 | status_notifier_item_register 42 | status_notifier_item_get_state 43 | 44 | STATUS_NOTIFIER_IS_ITEM 45 | STATUS_NOTIFIER_IS_ITEM_CLASS 46 | STATUS_NOTIFIER_ITEM 47 | STATUS_NOTIFIER_ITEM_CLASS 48 | STATUS_NOTIFIER_ITEM_GET_CLASS 49 | StatusNotifierItemPrivate 50 | STATUS_NOTIFIER_TYPE_ITEM 51 | status_notifier_item_get_type 52 | TYPE_STATUS_NOTIFIER_CATEGORY 53 | TYPE_STATUS_NOTIFIER_ERROR 54 | TYPE_STATUS_NOTIFIER_ICON 55 | TYPE_STATUS_NOTIFIER_SCROLL_ORIENTATION 56 | TYPE_STATUS_NOTIFIER_STATE 57 | TYPE_STATUS_NOTIFIER_STATUS 58 | status_notifier_category_get_type 59 | status_notifier_error_get_type 60 | status_notifier_icon_get_type 61 | status_notifier_scroll_orientation_get_type 62 | status_notifier_state_get_type 63 | status_notifier_status_get_type 64 | ITEM_INTERFACE 65 | ITEM_NAME 66 | ITEM_OBJECT 67 | WATCHER_INTERFACE 68 | WATCHER_NAME 69 | WATCHER_OBJECT 70 | g_cclosure_user_marshal_BOOLEAN__INT_INT 71 |
72 | 73 | -------------------------------------------------------------------------------- /docs/reference/statusnotifier.types: -------------------------------------------------------------------------------- 1 | status_notifier_item_get_type 2 | status_notifier_category_get_type 3 | status_notifier_error_get_type 4 | status_notifier_icon_get_type 5 | status_notifier_scroll_orientation_get_type 6 | status_notifier_status_get_type 7 | -------------------------------------------------------------------------------- /docs/reference/version.xml.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_VERSION@ 2 | -------------------------------------------------------------------------------- /example/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | bin_PROGRAMS = sn-example 3 | 4 | AM_CPPFLAGS = -I$(top_srcdir)/src 5 | 6 | sn_example_CFLAGS = ${AM_CFLAGS} @GTK_CFLAGS@ 7 | sn_example_LDADD = $(top_builddir)/.libs/libstatusnotifier.la @GTK_LIBS@ 8 | sn_example_SOURCES = sn-example.c 9 | 10 | -------------------------------------------------------------------------------- /example/sn-example.c: -------------------------------------------------------------------------------- 1 | /* 2 | * statusnotifier - Copyright (C) 2014-2017 Olivier Brunel 3 | * 4 | * sn-example.c 5 | * Copyright (C) 2014-2017 Olivier Brunel 6 | * 7 | * This file is part of statusnotifier. 8 | * 9 | * statusnotifier is free software: you can redistribute it and/or modify it 10 | * under the terms of the GNU General Public License as published by the Free 11 | * Software Foundation, either version 3 of the License, or (at your option) any 12 | * later version. 13 | * 14 | * statusnotifier is distributed in the hope that it will be useful, but WITHOUT 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * statusnotifier. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include "config.h" 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #define streq(s1, s2) (((s1) == NULL && (s2) == NULL) ? 1 \ 31 | : ((s1) == NULL || (s2) == NULL) ? 0 : strcmp ((s1), (s2)) == 0) 32 | 33 | #define EXAMPLE_ERROR g_quark_from_static_string ("Example error") 34 | enum rc 35 | { 36 | RC_OK = 0, 37 | RC_CMDLINE 38 | }; 39 | 40 | struct config 41 | { 42 | StatusNotifierCategory category; 43 | StatusNotifierStatus status; 44 | gchar *title; 45 | struct { 46 | gboolean has_pixbuf; 47 | union { 48 | gchar *icon_name; 49 | GdkPixbuf *pixbuf; 50 | }; 51 | } icon[_NB_STATUS_NOTIFIER_ICONS]; 52 | gchar *tooltip_title; 53 | gchar *tooltip_body; 54 | gboolean item_is_menu; 55 | #ifdef USE_DBUSMENU 56 | gboolean menu; 57 | #endif 58 | }; 59 | 60 | static void 61 | set_status (GObject *item, StatusNotifierItem *sn) 62 | { 63 | status_notifier_item_set_status (sn, GPOINTER_TO_UINT (g_object_get_data (item, "sn-status"))); 64 | } 65 | 66 | static void 67 | set_status_activation_trigger (gpointer item, gpointer sn) 68 | { 69 | g_signal_connect (item, "activate", (GCallback) set_status, sn); 70 | } 71 | 72 | static GtkMenu * 73 | create_menu (StatusNotifierItem *sn, GMainLoop *loop) 74 | { 75 | GtkMenu *menu; 76 | GtkMenu *submenu; 77 | GtkWidget *item; 78 | guint i; 79 | StatusNotifierStatus status; 80 | GSList *group = NULL; 81 | 82 | menu = (GtkMenu *) gtk_menu_new (); 83 | submenu = (GtkMenu *) gtk_menu_new (); 84 | 85 | g_object_get (sn, "status", &status, NULL); 86 | 87 | i = 0; 88 | 89 | item = gtk_radio_menu_item_new_with_label (group, "Passive"); 90 | group = gtk_radio_menu_item_get_group ((GtkRadioMenuItem *) item); 91 | if (status == STATUS_NOTIFIER_STATUS_PASSIVE) 92 | gtk_check_menu_item_set_active ((GtkCheckMenuItem *) item, TRUE); 93 | g_object_set_data ((GObject *) item, 94 | "sn-status", GUINT_TO_POINTER (STATUS_NOTIFIER_STATUS_PASSIVE)); 95 | gtk_widget_show (item); 96 | gtk_menu_attach (submenu, item, 0, 1, i, i + 1); 97 | ++i; 98 | item = gtk_radio_menu_item_new_with_label (group, "Active"); 99 | group = gtk_radio_menu_item_get_group ((GtkRadioMenuItem *) item); 100 | if (status == STATUS_NOTIFIER_STATUS_ACTIVE) 101 | gtk_check_menu_item_set_active ((GtkCheckMenuItem *) item, TRUE); 102 | g_object_set_data ((GObject *) item, 103 | "sn-status", GUINT_TO_POINTER (STATUS_NOTIFIER_STATUS_ACTIVE)); 104 | gtk_widget_show (item); 105 | gtk_menu_attach (submenu, item, 0, 1, i, i + 1); 106 | ++i; 107 | item = gtk_radio_menu_item_new_with_label (group, "Needs attention"); 108 | group = gtk_radio_menu_item_get_group ((GtkRadioMenuItem *) item); 109 | if (status == STATUS_NOTIFIER_STATUS_NEEDS_ATTENTION) 110 | gtk_check_menu_item_set_active ((GtkCheckMenuItem *) item, TRUE); 111 | g_object_set_data ((GObject *) item, 112 | "sn-status", GUINT_TO_POINTER (STATUS_NOTIFIER_STATUS_NEEDS_ATTENTION)); 113 | gtk_widget_show (item); 114 | gtk_menu_attach (submenu, item, 0, 1, i, i + 1); 115 | ++i; 116 | 117 | g_slist_foreach (group, &set_status_activation_trigger, sn); 118 | 119 | i = 0; 120 | item = gtk_menu_item_new_with_label ("Status"); 121 | gtk_menu_item_set_submenu ((GtkMenuItem *) item, (GtkWidget *) submenu); 122 | gtk_widget_show (item); 123 | gtk_menu_attach (menu, item, 0, 1, i, i + 1); 124 | ++i; 125 | item = gtk_menu_item_new_with_label ("Exit"); 126 | g_signal_connect_swapped (item, "activate", (GCallback) g_main_loop_quit, loop); 127 | gtk_widget_show (item); 128 | gtk_menu_attach (menu, item, 0, 1, i, i + 1); 129 | ++i; 130 | 131 | return menu; 132 | } 133 | 134 | static gboolean 135 | sn_menu (StatusNotifierItem *sn, gint x, gint y, GMainLoop *loop) 136 | { 137 | static GtkMenu *menu = NULL; 138 | if (!menu) 139 | { 140 | menu = create_menu (sn, loop); 141 | g_object_ref_sink (menu); 142 | } 143 | 144 | gtk_menu_popup (menu, NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ()); 145 | return TRUE; 146 | } 147 | 148 | static gboolean 149 | sn_activate (GMainLoop *loop) 150 | { 151 | g_main_loop_quit (loop); 152 | return TRUE; 153 | } 154 | 155 | static void 156 | sn_reg_failed (StatusNotifierItem *sn, GError *error, GMainLoop *loop) 157 | { 158 | fprintf (stderr, "Failed to create status notifier: %s\n", error->message); 159 | g_main_loop_quit (loop); 160 | } 161 | 162 | static gboolean 163 | cmdline_category (const gchar *option, 164 | const gchar *value, 165 | struct config *cfg, 166 | GError **error) 167 | { 168 | if (streq (value, "app")) 169 | cfg->category = STATUS_NOTIFIER_CATEGORY_APPLICATION_STATUS; 170 | else if (streq (value, "comm")) 171 | cfg->category = STATUS_NOTIFIER_CATEGORY_COMMUNICATIONS; 172 | else if (streq (value, "system")) 173 | cfg->category = STATUS_NOTIFIER_CATEGORY_SYSTEM_SERVICES; 174 | else if (streq (value, "hardware")) 175 | cfg->category = STATUS_NOTIFIER_CATEGORY_HARDWARE; 176 | else 177 | { 178 | g_set_error (error, EXAMPLE_ERROR, RC_CMDLINE, 179 | "Invalid category: '%s'; Must be 'app', 'comm', 'system' or 'hardware'", 180 | value); 181 | return FALSE; 182 | } 183 | 184 | return TRUE; 185 | } 186 | 187 | static gboolean 188 | cmdline_status (const gchar *option, 189 | const gchar *value, 190 | struct config *cfg, 191 | GError **error) 192 | { 193 | if (streq (value, "active")) 194 | cfg->status = STATUS_NOTIFIER_STATUS_ACTIVE; 195 | else if (streq (value, "passive")) 196 | cfg->status = STATUS_NOTIFIER_STATUS_PASSIVE; 197 | else if (streq (value, "attention")) 198 | cfg->status = STATUS_NOTIFIER_STATUS_NEEDS_ATTENTION; 199 | else 200 | { 201 | g_set_error (error, EXAMPLE_ERROR, RC_CMDLINE, 202 | "Invalid status: '%s'; Must be 'passive', 'active' or 'attention'", 203 | value); 204 | return FALSE; 205 | } 206 | 207 | return TRUE; 208 | } 209 | 210 | static void 211 | free_icon (struct config *cfg, StatusNotifierIcon icon) 212 | { 213 | if (cfg->icon[icon].has_pixbuf) 214 | { 215 | if (cfg->icon[icon].pixbuf) 216 | g_object_unref (cfg->icon[icon].pixbuf); 217 | } 218 | else 219 | g_free (cfg->icon[icon].icon_name); 220 | cfg->icon[icon].has_pixbuf = FALSE; 221 | cfg->icon[icon].icon_name = NULL; 222 | } 223 | 224 | static gboolean 225 | cmdline_icon_name (const gchar *option, 226 | const gchar *value, 227 | struct config *cfg, 228 | GError **error) 229 | { 230 | StatusNotifierIcon icon; 231 | 232 | if (streq (option, "-i") || streq (option, "--icon")) 233 | icon = STATUS_NOTIFIER_ICON; 234 | else if (streq (option, "-a") || streq (option, "--attention-icon")) 235 | icon = STATUS_NOTIFIER_ATTENTION_ICON; 236 | else if (streq (option, "-o") || streq (option, "--overlay-icon")) 237 | icon = STATUS_NOTIFIER_OVERLAY_ICON; 238 | else /* if (streq (option, "-l") || streq (option, "--tooltip-icon")) */ 239 | icon = STATUS_NOTIFIER_TOOLTIP_ICON; 240 | 241 | free_icon (cfg, icon); 242 | cfg->icon[icon].icon_name = g_strdup (value); 243 | return TRUE; 244 | } 245 | 246 | static gboolean 247 | cmdline_icon_pixbuf (const gchar *option, 248 | const gchar *value, 249 | struct config *cfg, 250 | GError **error) 251 | { 252 | StatusNotifierIcon icon; 253 | GdkPixbuf *pixbuf; 254 | 255 | if (streq (option, "-I") || streq (option, "--pixbuf")) 256 | icon = STATUS_NOTIFIER_ICON; 257 | else if (streq (option, "-A") || streq (option, "--attention-pixbuf")) 258 | icon = STATUS_NOTIFIER_ATTENTION_ICON; 259 | else if (streq (option, "-O") || streq (option, "--overlay-pixbuf")) 260 | icon = STATUS_NOTIFIER_OVERLAY_ICON; 261 | else /* if (streq (option, "-L") || streq (option, "--tooltip-pixbuf")) */ 262 | icon = STATUS_NOTIFIER_TOOLTIP_ICON; 263 | 264 | pixbuf = gdk_pixbuf_new_from_file (value, error); 265 | if (!pixbuf) 266 | { 267 | g_prefix_error (error, "Failed to load pixbuf from '%s': ", value); 268 | return FALSE; 269 | } 270 | 271 | free_icon (cfg, icon); 272 | cfg->icon[icon].pixbuf = pixbuf; 273 | cfg->icon[icon].has_pixbuf = TRUE; 274 | return TRUE; 275 | } 276 | 277 | static gboolean 278 | parse_cmdline (struct config *cfg, gint *argc, gchar **argv[], GError **error) 279 | { 280 | GOptionContext *context; 281 | GOptionEntry entries[] = 282 | { 283 | { "category", 'c', 0, G_OPTION_ARG_CALLBACK, cmdline_category, 284 | "Set the item's category;\n\t\t" 285 | "CATEGORY must be app, comm, system or hardware", "CATEGORY" }, 286 | { "title", 't', 0, G_OPTION_ARG_STRING, &cfg->title, 287 | "Set TITLE as the item's title", "TITLE" }, 288 | { "status", 's', 0, G_OPTION_ARG_CALLBACK, cmdline_status, 289 | "Set the item's status;\n\t\t" 290 | "STATUS must be active, passive or attention", "STATUS" }, 291 | { "icon", 'i', 0, G_OPTION_ARG_CALLBACK, cmdline_icon_name, 292 | "Use NAME as icon name for (main) icon", "NAME" }, 293 | { "pixbuf", 'I', 0, G_OPTION_ARG_CALLBACK, cmdline_icon_pixbuf, 294 | "Load FILE as icon for (main) icon", "FILE" }, 295 | { "attention-icon", 'a', 0, G_OPTION_ARG_CALLBACK, cmdline_icon_name, 296 | "Use NAME as icon name for attention icon", "NAME" }, 297 | { "attention-pixbuf", 'A', 0, G_OPTION_ARG_CALLBACK, cmdline_icon_pixbuf, 298 | "Load FILE as icon for attention icon", "FILE" }, 299 | { "overlay-icon", 'o', 0, G_OPTION_ARG_CALLBACK, cmdline_icon_name, 300 | "Use NAME as icon name for overlay icon", "NAME" }, 301 | { "overlay-pixbuf", 'O', 0, G_OPTION_ARG_CALLBACK, cmdline_icon_pixbuf, 302 | "Load FILE as icon for overlay icon", "FILE" }, 303 | { "tooltip-icon", 'l', 0, G_OPTION_ARG_CALLBACK, cmdline_icon_name, 304 | "Use NAME as icon name for tooltip icon", "NAME" }, 305 | { "tooltip-pixbuf", 'L', 0, G_OPTION_ARG_CALLBACK, cmdline_icon_pixbuf, 306 | "Load FILE as icon for tooltip icon", "FILE" }, 307 | { "tooltip", 'T', 0, G_OPTION_ARG_STRING, &cfg->tooltip_title, 308 | "Set TITLE as title of the item's tooltip", "TITLE" }, 309 | { "tooltip-body", 'b', 0, G_OPTION_ARG_STRING, &cfg->tooltip_body, 310 | "Set TEXT as body of the item's tooltip", "TEXT" }, 311 | { "item-is-menu", 'M', 0, G_OPTION_ARG_NONE, &cfg->item_is_menu, 312 | "Whether the item only supports context menu or not", NULL}, 313 | #ifdef USE_DBUSMENU 314 | { "dbus-menu", 'm', 0, G_OPTION_ARG_NONE, &cfg->menu, 315 | "Whether menu should be exposed via dbusmenu or not", NULL }, 316 | #endif 317 | { NULL } 318 | }; 319 | GOptionGroup *group; 320 | 321 | context = g_option_context_new (""); 322 | group = g_option_group_new ("example", "example", "app options", cfg, NULL); 323 | g_option_group_add_entries (group, entries); 324 | g_option_context_set_main_group (context, group); 325 | if (!g_option_context_parse (context, argc, argv, error)) 326 | return FALSE; 327 | 328 | return TRUE; 329 | } 330 | 331 | gint 332 | main (gint argc, gchar *argv[]) 333 | { 334 | GError *err = NULL; 335 | GMainLoop *loop; 336 | StatusNotifierItem *sn; 337 | struct config cfg = { 0, }; 338 | const gchar *prop_name_from_icon[_NB_STATUS_NOTIFIER_ICONS] = { 339 | "main-icon-name", 340 | "attention-icon-name", 341 | "overlay-icon-name", 342 | "tooltip-icon-name" 343 | }; 344 | const gchar *prop_pixbuf_from_icon[_NB_STATUS_NOTIFIER_ICONS] = { 345 | "main-icon-pixbuf", 346 | "attention-icon-pixbuf", 347 | "overlay-icon-pixbuf", 348 | "tooltip-icon-pixbuf" 349 | }; 350 | guint i; 351 | 352 | gtk_init (&argc, &argv); 353 | if (!parse_cmdline (&cfg, &argc, &argv, &err)) 354 | { 355 | fputs (err->message, stderr); 356 | fputc ('\n', stderr); 357 | g_clear_error (&err); 358 | return RC_CMDLINE; 359 | } 360 | 361 | loop = g_main_loop_new (NULL, TRUE); 362 | sn = g_object_new (STATUS_NOTIFIER_TYPE_ITEM, 363 | "id", "sn-example", 364 | "category", cfg.category, 365 | "status", cfg.status, 366 | "title", (cfg.title) ? cfg.title : "Example", 367 | "item-is-menu", cfg.item_is_menu, 368 | NULL); 369 | for (i = 0; i < _NB_STATUS_NOTIFIER_ICONS; ++i) 370 | { 371 | if (cfg.icon[i].has_pixbuf) 372 | g_object_set (sn, prop_pixbuf_from_icon[i], cfg.icon[i].pixbuf, NULL); 373 | else if (cfg.icon[i].icon_name) 374 | g_object_set (sn, prop_name_from_icon[i], cfg.icon[i].icon_name, NULL); 375 | } 376 | if (cfg.tooltip_title) 377 | status_notifier_item_set_tooltip_title (sn, cfg.tooltip_title); 378 | if (cfg.tooltip_body) 379 | status_notifier_item_set_tooltip_body (sn, cfg.tooltip_body); 380 | 381 | #ifdef USE_DBUSMENU 382 | if (cfg.menu) 383 | status_notifier_item_set_context_menu (sn, (GObject *) create_menu(sn, loop)); 384 | else 385 | #endif 386 | g_signal_connect (sn, "context-menu", (GCallback) sn_menu, loop); 387 | 388 | g_signal_connect (sn, "registration-failed", (GCallback) sn_reg_failed, loop); 389 | g_signal_connect_swapped (sn, "activate", (GCallback) sn_activate, loop); 390 | status_notifier_item_register (sn); 391 | g_main_loop_run (loop); 392 | 393 | g_object_unref (sn); 394 | return RC_OK; 395 | } 396 | -------------------------------------------------------------------------------- /m4/cflagsadd.m4: -------------------------------------------------------------------------------- 1 | dnl CFLAGS_ADD(PARAMETER, VARIABLE) 2 | dnl Adds parameter to VARIABLE if the compiler supports it. For example, 3 | dnl CFLAGS_ADD([-Wall],[WARN_FLAGS]). 4 | AC_DEFUN([CFLAGS_ADD], 5 | [AS_VAR_PUSHDEF([my_cflags], [cflags_cv_warn_$1])dnl 6 | AC_CACHE_CHECK([whether compiler handles $1], [my_cflags], [ 7 | save_CFLAGS="$CFLAGS" 8 | CFLAGS="${CFLAGS} $1" 9 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], 10 | [AS_VAR_SET([my_cflags], [yes])], 11 | [AS_VAR_SET([my_cflags], [no])]) 12 | CFLAGS="$save_CFLAGS" 13 | ]) 14 | AS_VAR_PUSHDEF([new_cflags], [[$2]])dnl 15 | AS_VAR_IF([my_cflags], [yes], [AS_VAR_APPEND([new_cflags], [" $1"])]) 16 | AS_VAR_POPDEF([new_cflags])dnl 17 | AS_VAR_POPDEF([my_cflags])dnl 18 | m4_ifval([$2], [AS_LITERAL_IF([$2], [AC_SUBST([$2])], [])])dnl 19 | ]) 20 | -------------------------------------------------------------------------------- /m4/introspection.m4: -------------------------------------------------------------------------------- 1 | dnl -*- mode: autoconf -*- 2 | dnl Copyright 2009 Johan Dahlin 3 | dnl 4 | dnl This file is free software; the author(s) gives unlimited 5 | dnl permission to copy and/or distribute it, with or without 6 | dnl modifications, as long as this notice is preserved. 7 | dnl 8 | 9 | # serial 1 10 | 11 | m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL], 12 | [ 13 | AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first 14 | AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first 15 | AC_BEFORE([LT_INIT],[$0])dnl setup libtool first 16 | 17 | dnl enable/disable introspection 18 | m4_if([$2], [require], 19 | [dnl 20 | enable_introspection=yes 21 | ],[dnl 22 | AC_ARG_ENABLE(introspection, 23 | AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]], 24 | [Enable introspection for this build]),, 25 | [enable_introspection=auto]) 26 | ])dnl 27 | 28 | AC_MSG_CHECKING([for gobject-introspection]) 29 | 30 | dnl presence/version checking 31 | AS_CASE([$enable_introspection], 32 | [no], [dnl 33 | found_introspection="no (disabled, use --enable-introspection to enable)" 34 | ],dnl 35 | [yes],[dnl 36 | PKG_CHECK_EXISTS([gobject-introspection-1.0],, 37 | AC_MSG_ERROR([gobject-introspection-1.0 is not installed])) 38 | PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], 39 | found_introspection=yes, 40 | AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build AC_PACKAGE_NAME])) 41 | ],dnl 42 | [auto],[dnl 43 | PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no) 44 | ],dnl 45 | [dnl 46 | AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of @<:@no/auto/yes@:>@]) 47 | ])dnl 48 | 49 | AC_MSG_RESULT([$found_introspection]) 50 | 51 | INTROSPECTION_SCANNER= 52 | INTROSPECTION_COMPILER= 53 | INTROSPECTION_GENERATE= 54 | INTROSPECTION_GIRDIR= 55 | INTROSPECTION_TYPELIBDIR= 56 | if test "x$found_introspection" = "xyes"; then 57 | INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0` 58 | INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0` 59 | INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0` 60 | INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0` 61 | INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)" 62 | INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0` 63 | INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0` 64 | INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection 65 | fi 66 | AC_SUBST(INTROSPECTION_SCANNER) 67 | AC_SUBST(INTROSPECTION_COMPILER) 68 | AC_SUBST(INTROSPECTION_GENERATE) 69 | AC_SUBST(INTROSPECTION_GIRDIR) 70 | AC_SUBST(INTROSPECTION_TYPELIBDIR) 71 | AC_SUBST(INTROSPECTION_CFLAGS) 72 | AC_SUBST(INTROSPECTION_LIBS) 73 | AC_SUBST(INTROSPECTION_MAKEFILE) 74 | 75 | AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes") 76 | ]) 77 | 78 | 79 | dnl Usage: 80 | dnl GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version]) 81 | 82 | AC_DEFUN([GOBJECT_INTROSPECTION_CHECK], 83 | [ 84 | _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1]) 85 | ]) 86 | 87 | dnl Usage: 88 | dnl GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version]) 89 | 90 | 91 | AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE], 92 | [ 93 | _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require]) 94 | ]) 95 | -------------------------------------------------------------------------------- /src/closures: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | glib-genmarshal --header closures.def >closures.h.new 4 | glib-genmarshal --body closures.def >closures.c.new 5 | 6 | -------------------------------------------------------------------------------- /src/closures.c: -------------------------------------------------------------------------------- 1 | /* 2 | * statusnotifier - Copyright (C) 2014 Olivier Brunel 3 | * 4 | * closures.c 5 | * Copyright (C) 2014 Olivier Brunel 6 | * 7 | * This file is part of statusnotifier. 8 | * 9 | * statusnotifier is free software: you can redistribute it and/or modify it 10 | * under the terms of the GNU General Public License as published by the Free 11 | * Software Foundation, either version 3 of the License, or (at your option) any 12 | * later version. 13 | * 14 | * statusnotifier is distributed in the hope that it will be useful, but WITHOUT 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * statusnotifier. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include 24 | #include "closures.h" 25 | 26 | 27 | #ifdef G_ENABLE_DEBUG 28 | #define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) 29 | #define g_marshal_value_peek_char(v) g_value_get_schar (v) 30 | #define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) 31 | #define g_marshal_value_peek_int(v) g_value_get_int (v) 32 | #define g_marshal_value_peek_uint(v) g_value_get_uint (v) 33 | #define g_marshal_value_peek_long(v) g_value_get_long (v) 34 | #define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) 35 | #define g_marshal_value_peek_int64(v) g_value_get_int64 (v) 36 | #define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) 37 | #define g_marshal_value_peek_enum(v) g_value_get_enum (v) 38 | #define g_marshal_value_peek_flags(v) g_value_get_flags (v) 39 | #define g_marshal_value_peek_float(v) g_value_get_float (v) 40 | #define g_marshal_value_peek_double(v) g_value_get_double (v) 41 | #define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) 42 | #define g_marshal_value_peek_param(v) g_value_get_param (v) 43 | #define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) 44 | #define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) 45 | #define g_marshal_value_peek_object(v) g_value_get_object (v) 46 | #define g_marshal_value_peek_variant(v) g_value_get_variant (v) 47 | #else /* !G_ENABLE_DEBUG */ 48 | /* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. 49 | * Do not access GValues directly in your code. Instead, use the 50 | * g_value_get_*() functions 51 | */ 52 | #define g_marshal_value_peek_boolean(v) (v)->data[0].v_int 53 | #define g_marshal_value_peek_char(v) (v)->data[0].v_int 54 | #define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint 55 | #define g_marshal_value_peek_int(v) (v)->data[0].v_int 56 | #define g_marshal_value_peek_uint(v) (v)->data[0].v_uint 57 | #define g_marshal_value_peek_long(v) (v)->data[0].v_long 58 | #define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong 59 | #define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 60 | #define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 61 | #define g_marshal_value_peek_enum(v) (v)->data[0].v_long 62 | #define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong 63 | #define g_marshal_value_peek_float(v) (v)->data[0].v_float 64 | #define g_marshal_value_peek_double(v) (v)->data[0].v_double 65 | #define g_marshal_value_peek_string(v) (v)->data[0].v_pointer 66 | #define g_marshal_value_peek_param(v) (v)->data[0].v_pointer 67 | #define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer 68 | #define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer 69 | #define g_marshal_value_peek_object(v) (v)->data[0].v_pointer 70 | #define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer 71 | #endif /* !G_ENABLE_DEBUG */ 72 | 73 | 74 | /* BOOLEAN:INT,INT (closures.def:1) */ 75 | void 76 | g_cclosure_user_marshal_BOOLEAN__INT_INT (GClosure *closure, 77 | GValue *return_value G_GNUC_UNUSED, 78 | guint n_param_values, 79 | const GValue *param_values, 80 | gpointer invocation_hint G_GNUC_UNUSED, 81 | gpointer marshal_data) 82 | { 83 | typedef gboolean (*GMarshalFunc_BOOLEAN__INT_INT) (gpointer data1, 84 | gint arg_1, 85 | gint arg_2, 86 | gpointer data2); 87 | register GMarshalFunc_BOOLEAN__INT_INT callback; 88 | register GCClosure *cc = (GCClosure*) closure; 89 | register gpointer data1, data2; 90 | gboolean v_return; 91 | 92 | g_return_if_fail (return_value != NULL); 93 | g_return_if_fail (n_param_values == 3); 94 | 95 | if (G_CCLOSURE_SWAP_DATA (closure)) 96 | { 97 | data1 = closure->data; 98 | data2 = g_value_peek_pointer (param_values + 0); 99 | } 100 | else 101 | { 102 | data1 = g_value_peek_pointer (param_values + 0); 103 | data2 = closure->data; 104 | } 105 | callback = (GMarshalFunc_BOOLEAN__INT_INT) (marshal_data ? marshal_data : cc->callback); 106 | 107 | v_return = callback (data1, 108 | g_marshal_value_peek_int (param_values + 1), 109 | g_marshal_value_peek_int (param_values + 2), 110 | data2); 111 | 112 | g_value_set_boolean (return_value, v_return); 113 | } 114 | 115 | -------------------------------------------------------------------------------- /src/closures.def: -------------------------------------------------------------------------------- 1 | BOOLEAN:INT,INT 2 | -------------------------------------------------------------------------------- /src/closures.h: -------------------------------------------------------------------------------- 1 | /* 2 | * statusnotifier - Copyright (C) 2014 Olivier Brunel 3 | * 4 | * closures.h 5 | * Copyright (C) 2014 Olivier Brunel 6 | * 7 | * This file is part of statusnotifier. 8 | * 9 | * statusnotifier is free software: you can redistribute it and/or modify it 10 | * under the terms of the GNU General Public License as published by the Free 11 | * Software Foundation, either version 3 of the License, or (at your option) any 12 | * later version. 13 | * 14 | * statusnotifier is distributed in the hope that it will be useful, but WITHOUT 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * statusnotifier. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef __g_cclosure_user_marshal_MARSHAL_H__ 24 | #define __g_cclosure_user_marshal_MARSHAL_H__ 25 | 26 | #include 27 | 28 | G_BEGIN_DECLS 29 | 30 | /* BOOLEAN:INT,INT (closures.def:1) */ 31 | extern void g_cclosure_user_marshal_BOOLEAN__INT_INT (GClosure *closure, 32 | GValue *return_value, 33 | guint n_param_values, 34 | const GValue *param_values, 35 | gpointer invocation_hint, 36 | gpointer marshal_data); 37 | 38 | G_END_DECLS 39 | 40 | #endif /* __g_cclosure_user_marshal_MARSHAL_H__ */ 41 | 42 | -------------------------------------------------------------------------------- /src/enums.c.template: -------------------------------------------------------------------------------- 1 | /*** BEGIN file-header ***/ 2 | 3 | #include "enums.h" 4 | /*** END file-header ***/ 5 | 6 | /*** BEGIN file-production ***/ 7 | /* enumerations from "statusnotifier.h" */ 8 | #include "statusnotifier.h" 9 | 10 | /*** END file-production ***/ 11 | 12 | 13 | /*** BEGIN value-header ***/ 14 | GType 15 | @enum_name@_get_type (void) 16 | { 17 | static GType etype = 0; 18 | 19 | if (etype == 0) 20 | { 21 | static const G@Type@Value values[] = { 22 | /*** END value-header ***/ 23 | 24 | /*** BEGIN value-production ***/ 25 | { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, 26 | /*** END value-production ***/ 27 | 28 | /*** BEGIN value-tail ***/ 29 | { 0, NULL, NULL } 30 | }; 31 | etype = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); 32 | } 33 | 34 | return etype; 35 | } 36 | 37 | /*** END value-tail ***/ 38 | 39 | /*** BEGIN file-tail ***/ 40 | 41 | /*** END file-tail ***/ 42 | -------------------------------------------------------------------------------- /src/enums.h.template: -------------------------------------------------------------------------------- 1 | /*** BEGIN file-header ***/ 2 | 3 | #ifndef STATUS_NOTIFIER_ENUMS_H 4 | #define STATUS_NOTIFIER_ENUMS_H 5 | 6 | #include "statusnotifier.h" 7 | 8 | G_BEGIN_DECLS 9 | /*** END file-header ***/ 10 | 11 | /*** BEGIN file-production ***/ 12 | 13 | /* enumerations from "statusnotifier.h" */ 14 | /*** END file-production ***/ 15 | 16 | /*** BEGIN value-header ***/ 17 | GType @enum_name@_get_type (void) G_GNUC_CONST; 18 | #define TYPE_@ENUMNAME@ (@enum_name@_get_type ()) 19 | /*** END value-header ***/ 20 | 21 | /*** BEGIN file-tail ***/ 22 | G_END_DECLS 23 | 24 | #endif /* !STATUS_NOTIFIER_ENUMS_H */ 25 | /*** END file-tail ***/ 26 | -------------------------------------------------------------------------------- /src/interfaces.h: -------------------------------------------------------------------------------- 1 | /* 2 | * statusnotifier - Copyright (C) 2014-2017 Olivier Brunel 3 | * 4 | * interfaces.h 5 | * Copyright (C) 2014-2017 Olivier Brunel 6 | * 7 | * This file is part of statusnotifier. 8 | * 9 | * statusnotifier is free software: you can redistribute it and/or modify it 10 | * under the terms of the GNU General Public License as published by the Free 11 | * Software Foundation, either version 3 of the License, or (at your option) any 12 | * later version. 13 | * 14 | * statusnotifier is distributed in the hope that it will be useful, but WITHOUT 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * statusnotifier. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef __INTERFACES_H__ 24 | #define __INTERFACES_H__ 25 | 26 | G_BEGIN_DECLS 27 | 28 | #define WATCHER_NAME "org.kde.StatusNotifierWatcher" 29 | #define WATCHER_OBJECT "/StatusNotifierWatcher" 30 | #define WATCHER_INTERFACE "org.kde.StatusNotifierWatcher" 31 | 32 | #define ITEM_NAME "org.kde.StatusNotifierItem" 33 | #define ITEM_OBJECT "/StatusNotifierItem" 34 | #define ITEM_INTERFACE "org.kde.StatusNotifierItem" 35 | 36 | static const gchar watcher_xml[] = 37 | "" 38 | " " 39 | " " 40 | " " 41 | " " 42 | " " 43 | " " 44 | " " 45 | " " 46 | ""; 47 | 48 | 49 | static const gchar item_xml[] = 50 | "" 51 | " " 52 | " " 53 | " " 54 | " " 55 | " " 56 | " " 57 | " " 58 | " " 59 | " " 60 | " " 61 | " " 62 | " " 63 | " " 64 | " " 65 | " " 66 | " " 67 | " " 68 | " " 69 | " " 70 | " " 71 | " " 72 | " " 73 | " " 74 | " " 75 | " " 76 | " " 77 | " " 78 | " " 79 | " " 80 | " " 81 | " " 82 | " " 83 | " " 84 | " " 85 | " " 86 | " " 87 | " " 88 | " " 89 | " " 90 | " " 91 | " " 92 | ""; 93 | 94 | G_END_DECLS 95 | 96 | #endif /* __INTERFACES_H__ */ 97 | -------------------------------------------------------------------------------- /src/mkenums: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | glib-mkenums \ 4 | --template enums.h.template \ 5 | statusnotifier.h > enums.h 6 | 7 | glib-mkenums \ 8 | --template enums.c.template \ 9 | statusnotifier.h > enums.c 10 | 11 | -------------------------------------------------------------------------------- /src/statusnotifier-compat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * statusnotifier - Copyright (C) 2014-2017 Olivier Brunel 3 | * 4 | * statusnotifier-compat.h 5 | * Copyright (C) 2017 Olivier Brunel 6 | * 7 | * This file is part of statusnotifier. 8 | * 9 | * statusnotifier is free software: you can redistribute it and/or modify it 10 | * under the terms of the GNU General Public License as published by the Free 11 | * Software Foundation, either version 3 of the License, or (at your option) any 12 | * later version. 13 | * 14 | * statusnotifier is distributed in the hope that it will be useful, but WITHOUT 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * statusnotifier. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef __STATUS_NOTIFIER_COMPAT_H__ 24 | #define __STATUS_NOTIFIER_COMPAT_H__ 25 | 26 | G_BEGIN_DECLS 27 | 28 | #define StatusNotifier StatusNotifierItem 29 | #define StatusNotifierPrivate StatusNotifierItemPrivate 30 | #define StatusNotifierClass StatusNotifierItemClass 31 | 32 | #define TYPE_STATUS_NOTIFIER STATUS_NOTIFIER_TYPE_ITEM 33 | #define STATUS_NOTIFIER STATUS_NOTIFIER_ITEM 34 | #define STATUS_NOTIFIER_CLASS STATUS_NOTIFIER_ITEM_CLASS 35 | #define IS_STATUS_NOTIFIER STATUS_NOTIFIER_IS_ITEM 36 | #define IS_STATUS_NOTIFIER_CLASS STATUS_NOTIFIER_IS_ITEM_CLASS 37 | #define STATUS_NOTIFIER_GET_CLASS STATUS_NOTIFIER_ITEM_GET_CLASS 38 | 39 | #define status_notifier_get_type status_notifier_item_get_type 40 | 41 | #define status_notifier_new_from_pixbuf status_notifier_item_new_from_pixbuf 42 | #define status_notifier_new_from_icon_name status_notifier_item_new_from_icon_name 43 | #define status_notifier_get_id status_notifier_item_get_id 44 | #define status_notifier_get_category status_notifier_item_get_category 45 | #define status_notifier_set_from_pixbuf status_notifier_item_set_from_pixbuf 46 | #define status_notifier_set_from_icon_name status_notifier_item_set_from_icon_name 47 | #define status_notifier_has_pixbuf status_notifier_item_has_pixbuf 48 | #define status_notifier_get_pixbuf status_notifier_item_get_pixbuf 49 | #define status_notifier_get_icon_name status_notifier_item_get_icon_name 50 | #define status_notifier_set_attention_movie_name \ 51 | status_notifier_item_set_attention_movie_name 52 | #define status_notifier_get_attention_movie_name \ 53 | status_notifier_item_get_attention_movie_name 54 | #define status_notifier_set_title status_notifier_item_set_title 55 | #define status_notifier_get_title status_notifier_item_get_title 56 | #define status_notifier_set_status status_notifier_item_set_status 57 | #define status_notifier_get_status status_notifier_item_get_status 58 | #define status_notifier_set_window_id status_notifier_item_set_window_id 59 | #define status_notifier_get_window_id status_notifier_item_get_window_id 60 | #define status_notifier_freeze_tooltip status_notifier_item_freeze_tooltip 61 | #define status_notifier_thaw_tooltip status_notifier_item_thaw_tooltip 62 | #define status_notifier_set_tooltip status_notifier_item_set_tooltip 63 | #define status_notifier_set_tooltip_title status_notifier_item_set_tooltip_title 64 | #define status_notifier_get_tooltip_title status_notifier_item_get_tooltip_title 65 | #define status_notifier_set_tooltip_body status_notifier_item_set_tooltip_body 66 | #define status_notifier_get_tooltip_body status_notifier_item_get_tooltip_body 67 | #define status_notifier_register status_notifier_item_register 68 | #define status_notifier_get_state status_notifier_item_get_state 69 | 70 | G_END_DECLS 71 | 72 | #endif /* __STATUS_NOTIFIER_COMPAT_H__ */ 73 | -------------------------------------------------------------------------------- /src/statusnotifier.c: -------------------------------------------------------------------------------- 1 | /* 2 | * statusnotifier - Copyright (C) 2014-2017 Olivier Brunel 3 | * 4 | * statusnotifier.c 5 | * Copyright (C) 2014-2017 Olivier Brunel 6 | * 7 | * This file is part of statusnotifier. 8 | * 9 | * statusnotifier is free software: you can redistribute it and/or modify it 10 | * under the terms of the GNU General Public License as published by the Free 11 | * Software Foundation, either version 3 of the License, or (at your option) any 12 | * later version. 13 | * 14 | * statusnotifier is distributed in the hope that it will be useful, but WITHOUT 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * statusnotifier. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #include "config.h" 24 | 25 | #include 26 | #include 27 | #include "statusnotifier.h" 28 | #include "enums.h" 29 | #include "interfaces.h" 30 | #include "closures.h" 31 | 32 | #if USE_DBUSMENU 33 | #include 34 | #include 35 | #include 36 | #include 37 | #endif 38 | 39 | #define _UNUSED_ __attribute__ ((unused)) 40 | 41 | /** 42 | * SECTION:statusnotifier 43 | * @Short_description: A StatusNotifierItem as per KDE's specifications 44 | * 45 | * Starting with Plasma Next, KDE doesn't support the XEmbed systray in favor of 46 | * their own Status Notifier Specification. 47 | * 48 | * A #StatusNotifierItem is a #GObject that can be used to represent a 49 | * StatusNotifierItem, handling all the DBus implementation and leaving you 50 | * simply dealing with regular properties and signals. 51 | * 52 | * You can simply create a new #StatusNotifierItem using one of the helper 53 | * function, e.g. status_notifier_item_new_from_icon_name(), or simply creating 54 | * an object as usual - you then just need to make sure to specify 55 | * #StatusNotifierItem:id : 56 | * 57 | * sn = (StatusNotifierItem *) g_object_new (STATUS_NOTIFIER_TYPE_ITEM, 58 | * "id", "app-id", 59 | * "status", STATUS_NOTIFIER_STATUS_NEEDS_ATTENTION, 60 | * "main-icon-name", "app-icon", 61 | * "attention-icon-pixbuf", pixbuf, 62 | * "tooltip-title", "My tooltip", 63 | * "tooltip-body", "This is an item about <b>app</b>", 64 | * NULL); 65 | * 66 | * 67 | * You can also set properties (other than id) after creation. Once ready, call 68 | * status_notifier_item_register() to register the item on the session bus and 69 | * to the StatusNotifierWatcher. 70 | * 71 | * If an error occurs, signal #StatusNotifierItem::registration-failed will be 72 | * emitted. On success, #StatusNotifierItem:state will be 73 | * %STATUS_NOTIFIER_STATE_REGISTERED. See status_notifier_item_register() for 74 | * more. 75 | * 76 | * Once registered, you can change properties as needed, and the proper DBus 77 | * signal will be emitted to let visualizations (hosts) know, and connect to the 78 | * signals (such as #StatusNotifierItem::context-menu) which will be emitted 79 | * when the corresponding DBus method was called. 80 | * 81 | * For reference, the specifications can be found at 82 | * https://freedesktop.org/wiki/Specifications/StatusNotifierItem/ 83 | * 84 | * Note that statusnotifier uses org.kde.* instead of the mentionned 85 | * org.freedesktop.* as the former was in the original specifications (still 86 | * available at http://www.notmart.org/misc/statusnotifieritem/index.html) and 87 | * seem to be the one actually in use. 88 | */ 89 | 90 | enum 91 | { 92 | PROP_0, 93 | 94 | PROP_ID, 95 | PROP_TITLE, 96 | PROP_CATEGORY, 97 | PROP_STATUS, 98 | PROP_MAIN_ICON_NAME, 99 | PROP_MAIN_ICON_PIXBUF, 100 | PROP_OVERLAY_ICON_NAME, 101 | PROP_OVERLAY_ICON_PIXBUF, 102 | PROP_ATTENTION_ICON_NAME, 103 | PROP_ATTENTION_ICON_PIXBUF, 104 | PROP_ATTENTION_MOVIE_NAME, 105 | PROP_TOOLTIP_ICON_NAME, 106 | PROP_TOOLTIP_ICON_PIXBUF, 107 | PROP_TOOLTIP_TITLE, 108 | PROP_TOOLTIP_BODY, 109 | PROP_ITEM_IS_MENU, 110 | PROP_MENU, 111 | PROP_WINDOW_ID, 112 | 113 | PROP_STATE, 114 | 115 | NB_PROPS 116 | }; 117 | 118 | static guint prop_name_from_icon[_NB_STATUS_NOTIFIER_ICONS] = { 119 | PROP_MAIN_ICON_NAME, 120 | PROP_ATTENTION_ICON_NAME, 121 | PROP_OVERLAY_ICON_NAME, 122 | PROP_TOOLTIP_ICON_NAME 123 | }; 124 | static guint prop_pixbuf_from_icon[_NB_STATUS_NOTIFIER_ICONS] = { 125 | PROP_MAIN_ICON_PIXBUF, 126 | PROP_ATTENTION_ICON_PIXBUF, 127 | PROP_OVERLAY_ICON_PIXBUF, 128 | PROP_TOOLTIP_ICON_PIXBUF 129 | }; 130 | 131 | enum 132 | { 133 | SIGNAL_REGISTRATION_FAILED, 134 | SIGNAL_CONTEXT_MENU, 135 | SIGNAL_ACTIVATE, 136 | SIGNAL_SECONDARY_ACTIVATE, 137 | SIGNAL_SCROLL, 138 | NB_SIGNALS 139 | }; 140 | 141 | struct _StatusNotifierItemPrivate 142 | { 143 | gchar *id; 144 | StatusNotifierCategory category; 145 | gchar *title; 146 | StatusNotifierStatus status; 147 | struct { 148 | gboolean has_pixbuf; 149 | union { 150 | gchar *icon_name; 151 | GdkPixbuf *pixbuf; 152 | }; 153 | } icon[_NB_STATUS_NOTIFIER_ICONS]; 154 | gchar *attention_movie_name; 155 | gchar *tooltip_title; 156 | gchar *tooltip_body; 157 | guint32 window_id; 158 | gboolean item_is_menu; 159 | 160 | guint tooltip_freeze; 161 | 162 | StatusNotifierState state; 163 | guint dbus_watch_id; 164 | gulong dbus_sid; 165 | guint dbus_owner_id; 166 | guint dbus_reg_id; 167 | GDBusProxy *dbus_proxy; 168 | #if USE_DBUSMENU 169 | DbusmenuServer *menu_service; 170 | GObject *menu; 171 | #endif 172 | GDBusConnection *dbus_conn; 173 | GError *dbus_err; 174 | }; 175 | 176 | static guint uniq_id = 0; 177 | 178 | static GParamSpec *status_notifier_item_props[NB_PROPS] = { NULL, }; 179 | static guint status_notifier_item_signals[NB_SIGNALS] = { 0, }; 180 | 181 | #define notify(sn,prop) \ 182 | g_object_notify_by_pspec ((GObject *) sn, status_notifier_item_props[prop]) 183 | 184 | static void status_notifier_item_set_property (GObject *object, 185 | guint prop_id, 186 | const GValue *value, 187 | GParamSpec *pspec); 188 | static void status_notifier_item_get_property (GObject *object, 189 | guint prop_id, 190 | GValue *value, 191 | GParamSpec *pspec); 192 | static void status_notifier_item_finalize (GObject *object); 193 | 194 | G_DEFINE_TYPE (StatusNotifierItem, status_notifier_item, G_TYPE_OBJECT) 195 | 196 | static void 197 | status_notifier_item_class_init (StatusNotifierItemClass *klass) 198 | { 199 | GObjectClass *o_class; 200 | 201 | o_class = G_OBJECT_CLASS (klass); 202 | o_class->set_property = status_notifier_item_set_property; 203 | o_class->get_property = status_notifier_item_get_property; 204 | o_class->finalize = status_notifier_item_finalize; 205 | 206 | /** 207 | * StatusNotifierItem:id: 208 | * 209 | * It's a name that should be unique for this application and consistent 210 | * between sessions, such as the application name itself. 211 | */ 212 | status_notifier_item_props[PROP_ID] = 213 | g_param_spec_string ("id", "id", "Unique application identifier", 214 | NULL, 215 | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); 216 | 217 | /** 218 | * StatusNotifierItem:title: 219 | * 220 | * It's a name that describes the application, it can be more descriptive 221 | * than #StatusNotifierItem:id. 222 | */ 223 | status_notifier_item_props[PROP_TITLE] = 224 | g_param_spec_string ("title", "title", "Descriptive name for the item", 225 | NULL, 226 | G_PARAM_READWRITE); 227 | 228 | /** 229 | * StatusNotifierItem:category: 230 | * 231 | * Describes the category of this item. 232 | */ 233 | status_notifier_item_props[PROP_CATEGORY] = 234 | g_param_spec_enum ("category", "category", "Category of the item", 235 | TYPE_STATUS_NOTIFIER_CATEGORY, 236 | STATUS_NOTIFIER_CATEGORY_APPLICATION_STATUS, 237 | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); 238 | 239 | /** 240 | * StatusNotifierItem:status: 241 | * 242 | * Describes the status of this item or of the associated application. 243 | */ 244 | status_notifier_item_props[PROP_STATUS] = 245 | g_param_spec_enum ("status", "status", "Status of the item", 246 | TYPE_STATUS_NOTIFIER_STATUS, 247 | STATUS_NOTIFIER_STATUS_PASSIVE, 248 | G_PARAM_READWRITE); 249 | 250 | /** 251 | * StatusNotifierItem:main-icon-name: 252 | * 253 | * The item can carry an icon that can be used by the visualization to 254 | * identify the item. 255 | * 256 | * An icon can either be identified by its Freedesktop-compliant icon name, 257 | * set by this property, or by the icon data itself, set by the property 258 | * #StatusNotifierItem:main-icon-pixbuf. 259 | * 260 | * It is currently not possible to set both, as setting one will unset the 261 | * other. 262 | */ 263 | status_notifier_item_props[PROP_MAIN_ICON_NAME] = 264 | g_param_spec_string ("main-icon-name", "main-icon-name", 265 | "Icon name for the main icon", 266 | NULL, 267 | G_PARAM_READWRITE); 268 | 269 | /** 270 | * StatusNotifierItem:main-icon-pixbuf: 271 | * 272 | * The item can carry an icon that can be used by the visualization to 273 | * identify the item. 274 | * 275 | * An icon can either be identified by its Freedesktop-compliant icon name, 276 | * set by property #StatusNotifierItem:main-icon-name, or by the icon data 277 | * itself, set by this property. 278 | * 279 | * It is currently not possible to set both, as setting one will unset the 280 | * other. 281 | */ 282 | status_notifier_item_props[PROP_MAIN_ICON_PIXBUF] = 283 | g_param_spec_object ("main-icon-pixbuf", "main-icon-pixbuf", 284 | "Pixbuf for the main icon", 285 | GDK_TYPE_PIXBUF, 286 | G_PARAM_READWRITE); 287 | 288 | /** 289 | * StatusNotifierItem:overlay-icon-name: 290 | * 291 | * This can be used by the visualization to indicate extra state 292 | * information, for instance as an overlay for the main icon. 293 | * 294 | * An icon can either be identified by its Freedesktop-compliant icon name, 295 | * set by this property, or by the icon data itself, set by property 296 | * #StatusNotifierItem:overlay-icon-pixbuf. 297 | * 298 | * It is currently not possible to set both, as setting one will unset the 299 | * other. 300 | */ 301 | status_notifier_item_props[PROP_OVERLAY_ICON_NAME] = 302 | g_param_spec_string ("overlay-icon-name", "overlay-icon-name", 303 | "Icon name for the overlay icon", 304 | NULL, 305 | G_PARAM_READWRITE); 306 | 307 | /** 308 | * StatusNotifierItem:overlay-icon-pixbuf: 309 | * 310 | * This can be used by the visualization to indicate extra state 311 | * information, for instance as an overlay for the main icon. 312 | * 313 | * An icon can either be identified by its Freedesktop-compliant icon name, 314 | * set by property #StatusNotifierItem:overlay-icon-name, or by the icon 315 | * data itself, set by this property. 316 | * 317 | * It is currently not possible to set both, as setting one will unset the 318 | * other. 319 | */ 320 | status_notifier_item_props[PROP_OVERLAY_ICON_PIXBUF] = 321 | g_param_spec_object ("overlay-icon-pixbuf", "overlay-icon-pixbuf", 322 | "Pixbuf for the overlay icon", 323 | GDK_TYPE_PIXBUF, 324 | G_PARAM_READWRITE); 325 | 326 | /** 327 | * StatusNotifierItem:attention-icon-name: 328 | * 329 | * This can be used by the visualization to indicate that the item is in 330 | * %STATUS_NOTIFIER_STATUS_NEEDS_ATTENTION status. 331 | * 332 | * An icon can either be identified by its Freedesktop-compliant icon name, 333 | * set by this property, or by the icon data itself, set by property 334 | * #StatusNotifierItem:attention-icon-pixbuf. 335 | * 336 | * It is currently not possible to set both, as setting one will unset the 337 | * other. 338 | */ 339 | status_notifier_item_props[PROP_ATTENTION_ICON_NAME] = 340 | g_param_spec_string ("attention-icon-name", "attention-icon-name", 341 | "Icon name for the attention icon", 342 | NULL, 343 | G_PARAM_READWRITE); 344 | 345 | /** 346 | * StatusNotifierItem:attention-icon-pixbuf: 347 | * 348 | * This can be used by the visualization to indicate that the item is in 349 | * %STATUS_NOTIFIER_STATUS_NEEDS_ATTENTION status. 350 | * 351 | * An icon can either be identified by its Freedesktop-compliant icon name, 352 | * set by property #StatusNotifierItem:attention-icon-name, or by the icon 353 | * data itself, set by this property. 354 | * 355 | * It is currently not possible to set both, as setting one will unset the 356 | * other. 357 | */ 358 | status_notifier_item_props[PROP_ATTENTION_ICON_PIXBUF] = 359 | g_param_spec_object ("attention-icon-pixbuf", "attention-icon-pixbuf", 360 | "Pixbuf for the attention icon", 361 | GDK_TYPE_PIXBUF, 362 | G_PARAM_READWRITE); 363 | 364 | /** 365 | * StatusNotifierItem:attention-movie-name: 366 | * 367 | * In addition to the icon, the item can also specify an animation 368 | * associated to the #STATUS_NOTIFIER_STATUS_NEEDS_ATTENTION status. 369 | * 370 | * This should be either a Freedesktop-compliant icon name or a full path. 371 | * The visualization can chose between the movie or icon (or using neither 372 | * of those) at its discretion. 373 | */ 374 | status_notifier_item_props[PROP_ATTENTION_MOVIE_NAME] = 375 | g_param_spec_string ("attention-movie-name", "attention-movie-name", 376 | "Animation name/full path when the item is in needs-attention status", 377 | NULL, 378 | G_PARAM_READWRITE); 379 | 380 | /** 381 | * StatusNotifierItem:tooltip-icon-name: 382 | * 383 | * A tooltip can be defined on the item; It can be used by the visualization 384 | * to show as a tooltip (or by any other mean it considers appropriate). 385 | * 386 | * The tooltip is composed of a title, a body, and an icon. Note that 387 | * changing any of these will trigger a DBus signal NewToolTip (for hosts to 388 | * refresh DBus property ToolTip), see status_notifier_item_freeze_tooltip() 389 | * for changing more than one and only emitting one DBus signal at the end. 390 | * 391 | * The icon can either be identified by its Freedesktop-compliant icon name, 392 | * set by this property, or by the icon data itself, set by property 393 | * #StatusNotifierItem:tooltip-icon-pixbuf. 394 | * 395 | * It is currently not possible to set both, as setting one will unset the 396 | * other. 397 | */ 398 | status_notifier_item_props[PROP_TOOLTIP_ICON_NAME] = 399 | g_param_spec_string ("tooltip-icon-name", "tooltip-icon-name", 400 | "Icon name for the tooltip icon", 401 | NULL, 402 | G_PARAM_READWRITE); 403 | 404 | /** 405 | * StatusNotifierItem:tooltip-icon-pixbuf: 406 | * 407 | * A tooltip can be defined on the item; It can be used by the visualization 408 | * to show as a tooltip (or by any other mean it considers appropriate). 409 | * 410 | * The tooltip is composed of a title, a body, and an icon. Note that 411 | * changing any of these will trigger a DBus signal NewToolTip (for hosts to 412 | * refresh DBus property ToolTip), see status_notifier_item_freeze_tooltip() 413 | * for changing more than one and only emitting one DBus signal at the end. 414 | * 415 | * The icon can either be identified by its Freedesktop-compliant icon name, 416 | * set by property #StatusNotifierItem:tooltip-icon-name, or by the icon 417 | * data itself, set by this property. 418 | * 419 | * It is currently not possible to set both, as setting one will unset the 420 | * other. 421 | */ 422 | status_notifier_item_props[PROP_TOOLTIP_ICON_PIXBUF] = 423 | g_param_spec_object ("tooltip-icon-pixbuf", "tooltip-icon-pixbuf", 424 | "Pixbuf for the tooltip icon", 425 | GDK_TYPE_PIXBUF, 426 | G_PARAM_READWRITE); 427 | 428 | /** 429 | * StatusNotifierItem:tooltip-title: 430 | * 431 | * A tooltip can be defined on the item; It can be used by the visualization 432 | * to show as a tooltip (or by any other mean it considers appropriate). 433 | * 434 | * The tooltip is composed of a title, a body, and an icon. Note that 435 | * changing any of these will trigger a DBus signal NewToolTip (for hosts to 436 | * refresh DBus property ToolTip), see status_notifier_item_freeze_tooltip() 437 | * for changing more than one and only emitting one DBus signal at the end. 438 | */ 439 | status_notifier_item_props[PROP_TOOLTIP_TITLE] = 440 | g_param_spec_string ("tooltip-title", "tooltip-title", 441 | "Title of the tooltip", 442 | NULL, 443 | G_PARAM_READWRITE); 444 | 445 | /** 446 | * StatusNotifierItem:tooltip-body: 447 | * 448 | * A tooltip can be defined on the item; It can be used by the visualization 449 | * to show as a tooltip (or by any other mean it considers appropriate). 450 | * 451 | * The tooltip is composed of a title, a body, and an icon. Note that 452 | * changing any of these will trigger a DBus signal NewToolTip (for hosts to 453 | * refresh DBus property ToolTip), see status_notifier_item_freeze_tooltip() 454 | * for changing more than one and only emitting one DBus signal at the end. 455 | * 456 | * This body can contain some markup, which consists of a small subset of 457 | * XHTML. See 458 | * https://freedesktop.org/wiki/Specifications/StatusNotifierItem/Markup/ 459 | * for more. 460 | */ 461 | status_notifier_item_props[PROP_TOOLTIP_BODY] = 462 | g_param_spec_string ("tooltip-body", "tooltip-body", 463 | "Body of the tooltip", 464 | NULL, 465 | G_PARAM_READWRITE); 466 | 467 | 468 | /** 469 | * StatusNotifierItem:item-is-menu: 470 | * 471 | * Whether or not this #StatusNotifierItem only supports a context menu or 472 | * not. See status_notifier_item_set_item_is_menu() for more. 473 | * 474 | * Since: 1.0.0 475 | */ 476 | status_notifier_item_props[PROP_ITEM_IS_MENU] = 477 | g_param_spec_boolean ("item-is-menu", "item-is-menu", 478 | "Whether or not the item only supports context menu", 479 | FALSE, 480 | G_PARAM_READWRITE); 481 | 482 | /** 483 | * StatusNotifierItem:menu: 484 | * 485 | * A #GtkMenu can be exposed via DBusMenu protocol to have native Look&Feel. 486 | * When menu is exposed, no "context-menu" signals will be received. 487 | * 488 | * Only writable if dbusmenu support was enabled during compilation. See 489 | * status_notifier_item_set_context_menu() for how to check whether it is 490 | * available or not. 491 | * 492 | * Since: 1.0.0 493 | */ 494 | status_notifier_item_props[PROP_MENU] = 495 | g_param_spec_object ("menu", "menu", 496 | "Context menu to be exposed via dbus", 497 | G_TYPE_OBJECT, 498 | #if USE_DBUSMENU 499 | G_PARAM_READWRITE 500 | #else 501 | G_PARAM_READABLE 502 | #endif 503 | ); 504 | 505 | /** 506 | * StatusNotifierItem:window-id: 507 | * 508 | * It's the windowing-system dependent identifier for a window, the 509 | * application can chose one of its windows to be available trough this 510 | * property or just set 0 if it's not interested. 511 | */ 512 | status_notifier_item_props[PROP_WINDOW_ID] = 513 | g_param_spec_uint ("window-id", "window-id", "Window ID", 514 | 0, G_MAXUINT32, 515 | 0, 516 | G_PARAM_READWRITE); 517 | 518 | /** 519 | * StatusNotifierItem:state: 520 | * 521 | * The state of the item, regarding its DBus registration on the 522 | * StatusNotifierWatcher. After you've created the item, you need to call 523 | * status_notifier_item_register() to have it registered via DBus on the watcher. 524 | * 525 | * See status_notifier_item_register() for more. 526 | */ 527 | status_notifier_item_props[PROP_STATE] = 528 | g_param_spec_enum ("state", "state", 529 | "DBus registration state of the item", 530 | TYPE_STATUS_NOTIFIER_STATE, 531 | STATUS_NOTIFIER_STATE_NOT_REGISTERED, 532 | G_PARAM_READABLE); 533 | 534 | g_object_class_install_properties (o_class, NB_PROPS, status_notifier_item_props); 535 | 536 | /** 537 | * StatusNotifierItem::registration-failed: 538 | * @sn: The #StatusNotifierItem 539 | * @error: A #GError with the reason of failure 540 | * 541 | * This signal is emited after a call to status_notifier_item_register() 542 | * when registering the item eventually failed (e.g. if there wasn't (yet) 543 | * any StatusNotifierHost registered.) 544 | * 545 | * When this happens, you should fallback to using the systray. You should 546 | * also check #StatusNotifierItem:state as it might still be 547 | * %STATUS_NOTIFIER_STATE_REGISTERING if the registration remains eventually 548 | * possible (e.g. waiting for a StatusNotifierHost to register) 549 | * 550 | * See status_notifier_item_register() for more. 551 | */ 552 | status_notifier_item_signals[SIGNAL_REGISTRATION_FAILED] = g_signal_new ( 553 | "registration-failed", 554 | STATUS_NOTIFIER_TYPE_ITEM, 555 | G_SIGNAL_RUN_LAST, 556 | G_STRUCT_OFFSET (StatusNotifierItemClass, registration_failed), 557 | NULL, 558 | NULL, 559 | g_cclosure_marshal_VOID__BOXED, 560 | G_TYPE_NONE, 561 | 1, 562 | G_TYPE_ERROR); 563 | 564 | /** 565 | * StatusNotifierItem::context-menu: 566 | * @sn: The #StatusNotifierItem 567 | * @x: screen coordinates X 568 | * @y: screen coordinates Y 569 | * 570 | * Emitted when the ContextMenu method was called on the item. Item should 571 | * then show a context menu, this is typically a consequence of user input, 572 | * such as mouse right click over the graphical representation of the item. 573 | * 574 | * @x and @y are to be considered an hint to the item about where to show 575 | * the context menu. 576 | */ 577 | status_notifier_item_signals[SIGNAL_CONTEXT_MENU] = g_signal_new ( 578 | "context-menu", 579 | STATUS_NOTIFIER_TYPE_ITEM, 580 | G_SIGNAL_RUN_LAST, 581 | G_STRUCT_OFFSET (StatusNotifierItemClass, context_menu), 582 | g_signal_accumulator_true_handled, 583 | NULL, 584 | g_cclosure_user_marshal_BOOLEAN__INT_INT, 585 | G_TYPE_BOOLEAN, 586 | 2, 587 | G_TYPE_INT, 588 | G_TYPE_INT); 589 | 590 | /** 591 | * StatusNotifierItem::activate: 592 | * @sn: The #StatusNotifierItem 593 | * @x: screen coordinates X 594 | * @y: screen coordinates Y 595 | * 596 | * Emitted when the Activate method was called on the item. Activation of 597 | * the item was requested, this is typically a consequence of user input, 598 | * such as mouse left click over the graphical representation of the item. 599 | * 600 | * @x and @y are to be considered an hint to the item about where to show 601 | * the context menu. 602 | */ 603 | status_notifier_item_signals[SIGNAL_ACTIVATE] = g_signal_new ( 604 | "activate", 605 | STATUS_NOTIFIER_TYPE_ITEM, 606 | G_SIGNAL_RUN_LAST, 607 | G_STRUCT_OFFSET (StatusNotifierItemClass, activate), 608 | g_signal_accumulator_true_handled, 609 | NULL, 610 | g_cclosure_user_marshal_BOOLEAN__INT_INT, 611 | G_TYPE_BOOLEAN, 612 | 2, 613 | G_TYPE_INT, 614 | G_TYPE_INT); 615 | 616 | /** 617 | * StatusNotifierItem::secondary-activate: 618 | * @sn: The #StatusNotifierItem 619 | * @x: screen coordinates X 620 | * @y: screen coordinates Y 621 | * 622 | * Emitted when the SecondaryActivate method was called on the item. 623 | * Secondary and less important form of activation (compared to 624 | * #StatusNotifierItem::activate) of the item was requested. This is 625 | * typically a consequence of user input, such as mouse middle click over 626 | * the graphical representation of the item. 627 | * 628 | * @x and @y are to be considered an hint to the item about where to show 629 | * the context menu. 630 | */ 631 | status_notifier_item_signals[SIGNAL_SECONDARY_ACTIVATE] = g_signal_new ( 632 | "secondary-activate", 633 | STATUS_NOTIFIER_TYPE_ITEM, 634 | G_SIGNAL_RUN_LAST, 635 | G_STRUCT_OFFSET (StatusNotifierItemClass, secondary_activate), 636 | g_signal_accumulator_true_handled, 637 | NULL, 638 | g_cclosure_user_marshal_BOOLEAN__INT_INT, 639 | G_TYPE_BOOLEAN, 640 | 2, 641 | G_TYPE_INT, 642 | G_TYPE_INT); 643 | 644 | /** 645 | * StatusNotifierItem::scroll: 646 | * @sn: The #StatusNotifierItem 647 | * @delta: the amount of scroll 648 | * @orientation: orientation of the scroll request 649 | * 650 | * Emitted when the Scroll method was called on the item. The user asked for 651 | * a scroll action. This is caused from input such as mouse wheel over the 652 | * graphical representation of the item. 653 | */ 654 | status_notifier_item_signals[SIGNAL_SCROLL] = g_signal_new ( 655 | "scroll", 656 | STATUS_NOTIFIER_TYPE_ITEM, 657 | G_SIGNAL_RUN_LAST, 658 | G_STRUCT_OFFSET (StatusNotifierItemClass, scroll), 659 | g_signal_accumulator_true_handled, 660 | NULL, 661 | g_cclosure_user_marshal_BOOLEAN__INT_INT, 662 | G_TYPE_BOOLEAN, 663 | 2, 664 | G_TYPE_INT, 665 | TYPE_STATUS_NOTIFIER_SCROLL_ORIENTATION); 666 | 667 | g_type_class_add_private (klass, sizeof (StatusNotifierItemPrivate)); 668 | } 669 | 670 | static void 671 | status_notifier_item_init (StatusNotifierItem *sn) 672 | { 673 | sn->priv = G_TYPE_INSTANCE_GET_PRIVATE (sn, 674 | STATUS_NOTIFIER_TYPE_ITEM, StatusNotifierItemPrivate); 675 | } 676 | 677 | static void 678 | status_notifier_item_set_property (GObject *object, 679 | guint prop_id, 680 | const GValue *value, 681 | GParamSpec *pspec) 682 | { 683 | StatusNotifierItem *sn = (StatusNotifierItem *) object; 684 | StatusNotifierItemPrivate *priv = sn->priv; 685 | 686 | switch (prop_id) 687 | { 688 | case PROP_ID: /* G_PARAM_CONSTRUCT_ONLY */ 689 | priv->id = g_value_dup_string (value); 690 | break; 691 | case PROP_TITLE: 692 | status_notifier_item_set_title (sn, g_value_get_string (value)); 693 | break; 694 | case PROP_CATEGORY: /* G_PARAM_CONSTRUCT_ONLY */ 695 | priv->category = g_value_get_enum (value); 696 | break; 697 | case PROP_STATUS: 698 | status_notifier_item_set_status (sn, g_value_get_enum (value)); 699 | break; 700 | case PROP_MAIN_ICON_NAME: 701 | status_notifier_item_set_from_icon_name (sn, STATUS_NOTIFIER_ICON, 702 | g_value_get_string (value)); 703 | break; 704 | case PROP_MAIN_ICON_PIXBUF: 705 | status_notifier_item_set_from_pixbuf (sn, STATUS_NOTIFIER_ICON, 706 | g_value_get_object (value)); 707 | break; 708 | case PROP_OVERLAY_ICON_NAME: 709 | status_notifier_item_set_from_icon_name (sn, STATUS_NOTIFIER_OVERLAY_ICON, 710 | g_value_get_string (value)); 711 | break; 712 | case PROP_OVERLAY_ICON_PIXBUF: 713 | status_notifier_item_set_from_pixbuf (sn, STATUS_NOTIFIER_OVERLAY_ICON, 714 | g_value_get_object (value)); 715 | break; 716 | case PROP_ATTENTION_ICON_NAME: 717 | status_notifier_item_set_from_icon_name (sn, STATUS_NOTIFIER_ATTENTION_ICON, 718 | g_value_get_string (value)); 719 | break; 720 | case PROP_ATTENTION_ICON_PIXBUF: 721 | status_notifier_item_set_from_pixbuf (sn, STATUS_NOTIFIER_ATTENTION_ICON, 722 | g_value_get_object (value)); 723 | break; 724 | case PROP_ATTENTION_MOVIE_NAME: 725 | status_notifier_item_set_attention_movie_name (sn, g_value_get_string (value)); 726 | break; 727 | case PROP_TOOLTIP_ICON_NAME: 728 | status_notifier_item_set_from_icon_name (sn, STATUS_NOTIFIER_TOOLTIP_ICON, 729 | g_value_get_string (value)); 730 | break; 731 | case PROP_TOOLTIP_ICON_PIXBUF: 732 | status_notifier_item_set_from_pixbuf (sn, STATUS_NOTIFIER_TOOLTIP_ICON, 733 | g_value_get_object (value)); 734 | break; 735 | case PROP_TOOLTIP_TITLE: 736 | status_notifier_item_set_tooltip_title (sn, g_value_get_string (value)); 737 | break; 738 | case PROP_TOOLTIP_BODY: 739 | status_notifier_item_set_tooltip_body (sn, g_value_get_string (value)); 740 | break; 741 | case PROP_ITEM_IS_MENU: 742 | status_notifier_item_set_item_is_menu (sn, g_value_get_boolean (value)); 743 | break; 744 | #if USE_DBUSMENU 745 | case PROP_MENU: 746 | status_notifier_item_set_context_menu (sn, g_value_get_object (value)); 747 | break; 748 | #endif 749 | case PROP_WINDOW_ID: 750 | status_notifier_item_set_window_id (sn, g_value_get_uint (value)); 751 | break; 752 | default: 753 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 754 | break; 755 | } 756 | } 757 | 758 | static void 759 | status_notifier_item_get_property (GObject *object, 760 | guint prop_id, 761 | GValue *value, 762 | GParamSpec *pspec) 763 | { 764 | StatusNotifierItem *sn = (StatusNotifierItem *) object; 765 | StatusNotifierItemPrivate *priv = sn->priv; 766 | 767 | switch (prop_id) 768 | { 769 | case PROP_ID: 770 | g_value_set_string (value, priv->id); 771 | break; 772 | case PROP_TITLE: 773 | g_value_set_string (value, priv->title); 774 | break; 775 | case PROP_CATEGORY: 776 | g_value_set_enum (value, priv->category); 777 | break; 778 | case PROP_STATUS: 779 | g_value_set_enum (value, priv->status); 780 | break; 781 | case PROP_MAIN_ICON_NAME: 782 | g_value_take_string (value, status_notifier_item_get_icon_name (sn, 783 | STATUS_NOTIFIER_ICON)); 784 | break; 785 | case PROP_MAIN_ICON_PIXBUF: 786 | g_value_take_object (value, status_notifier_item_get_pixbuf (sn, 787 | STATUS_NOTIFIER_ICON)); 788 | break; 789 | case PROP_OVERLAY_ICON_NAME: 790 | g_value_take_string (value, status_notifier_item_get_icon_name (sn, 791 | STATUS_NOTIFIER_OVERLAY_ICON)); 792 | break; 793 | case PROP_OVERLAY_ICON_PIXBUF: 794 | g_value_take_object (value, status_notifier_item_get_pixbuf (sn, 795 | STATUS_NOTIFIER_OVERLAY_ICON)); 796 | break; 797 | case PROP_ATTENTION_ICON_NAME: 798 | g_value_take_string (value, status_notifier_item_get_icon_name (sn, 799 | STATUS_NOTIFIER_ATTENTION_ICON)); 800 | break; 801 | case PROP_ATTENTION_ICON_PIXBUF: 802 | g_value_take_object (value, status_notifier_item_get_pixbuf (sn, 803 | STATUS_NOTIFIER_ATTENTION_ICON)); 804 | break; 805 | case PROP_ATTENTION_MOVIE_NAME: 806 | g_value_set_string (value, priv->attention_movie_name); 807 | break; 808 | case PROP_TOOLTIP_ICON_NAME: 809 | g_value_take_string (value, status_notifier_item_get_icon_name (sn, 810 | STATUS_NOTIFIER_TOOLTIP_ICON)); 811 | break; 812 | case PROP_TOOLTIP_ICON_PIXBUF: 813 | g_value_take_object (value, status_notifier_item_get_pixbuf (sn, 814 | STATUS_NOTIFIER_TOOLTIP_ICON)); 815 | break; 816 | case PROP_TOOLTIP_TITLE: 817 | g_value_set_string (value, priv->tooltip_title); 818 | break; 819 | case PROP_TOOLTIP_BODY: 820 | g_value_set_string (value, priv->tooltip_body); 821 | break; 822 | case PROP_ITEM_IS_MENU: 823 | g_value_set_boolean (value, priv->item_is_menu); 824 | break; 825 | case PROP_MENU: 826 | g_value_set_object (value, status_notifier_item_get_context_menu (sn)); 827 | break; 828 | case PROP_WINDOW_ID: 829 | g_value_set_uint (value, priv->window_id); 830 | break; 831 | case PROP_STATE: 832 | g_value_set_enum (value, priv->state); 833 | break; 834 | default: 835 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 836 | break; 837 | } 838 | } 839 | 840 | static void 841 | free_icon (StatusNotifierItem *sn, StatusNotifierIcon icon) 842 | { 843 | StatusNotifierItemPrivate *priv = sn->priv; 844 | 845 | if (priv->icon[icon].has_pixbuf) 846 | g_object_unref (priv->icon[icon].pixbuf); 847 | else 848 | g_free (priv->icon[icon].icon_name); 849 | priv->icon[icon].has_pixbuf = FALSE; 850 | priv->icon[icon].icon_name = NULL; 851 | } 852 | 853 | static void 854 | dbus_free (StatusNotifierItem *sn) 855 | { 856 | StatusNotifierItemPrivate *priv = sn->priv; 857 | 858 | if (priv->dbus_watch_id > 0) 859 | { 860 | g_bus_unwatch_name (priv->dbus_watch_id); 861 | priv->dbus_watch_id = 0; 862 | } 863 | if (priv->dbus_sid > 0) 864 | { 865 | g_signal_handler_disconnect (priv->dbus_proxy, priv->dbus_sid); 866 | priv->dbus_sid = 0; 867 | } 868 | if (G_LIKELY (priv->dbus_owner_id > 0)) 869 | { 870 | g_bus_unown_name (priv->dbus_owner_id); 871 | priv->dbus_owner_id = 0; 872 | } 873 | if (priv->dbus_proxy) 874 | { 875 | g_object_unref (priv->dbus_proxy); 876 | priv->dbus_proxy = NULL; 877 | } 878 | #if USE_DBUSMENU 879 | if (priv->menu) 880 | { 881 | g_object_unref (priv->menu); 882 | priv->menu = NULL; 883 | } 884 | if (priv->menu_service) 885 | { 886 | g_object_unref (priv->menu_service); 887 | priv->menu_service = NULL; 888 | } 889 | #endif 890 | if (priv->dbus_reg_id > 0) 891 | { 892 | g_dbus_connection_unregister_object (priv->dbus_conn, priv->dbus_reg_id); 893 | priv->dbus_reg_id = 0; 894 | } 895 | if (priv->dbus_conn) 896 | { 897 | g_object_unref (priv->dbus_conn); 898 | priv->dbus_conn = NULL; 899 | } 900 | } 901 | 902 | static void 903 | status_notifier_item_finalize (GObject *object) 904 | { 905 | StatusNotifierItem *sn = (StatusNotifierItem *) object; 906 | StatusNotifierItemPrivate *priv = sn->priv; 907 | guint i; 908 | 909 | g_free (priv->id); 910 | g_free (priv->title); 911 | for (i = 0; i < _NB_STATUS_NOTIFIER_ICONS; ++i) 912 | free_icon (sn, i); 913 | g_free (priv->attention_movie_name); 914 | g_free (priv->tooltip_title); 915 | g_free (priv->tooltip_body); 916 | 917 | dbus_free (sn); 918 | 919 | G_OBJECT_CLASS (status_notifier_item_parent_class)->finalize (object); 920 | } 921 | 922 | static void 923 | dbus_notify (StatusNotifierItem *sn, guint prop) 924 | { 925 | StatusNotifierItemPrivate *priv = sn->priv; 926 | const gchar *signal; 927 | 928 | if (priv->state != STATUS_NOTIFIER_STATE_REGISTERED) 929 | return; 930 | 931 | switch (prop) 932 | { 933 | case PROP_STATUS: 934 | { 935 | const gchar const *s_status[] = { 936 | "Passive", 937 | "Active", 938 | "NeedsAttention" 939 | }; 940 | signal = "NewStatus"; 941 | g_dbus_connection_emit_signal (priv->dbus_conn, 942 | NULL, 943 | ITEM_OBJECT, 944 | ITEM_INTERFACE, 945 | signal, 946 | g_variant_new ("(s)", s_status[priv->status]), 947 | NULL); 948 | return; 949 | } 950 | case PROP_TITLE: 951 | signal = "NewTitle"; 952 | break; 953 | case PROP_MAIN_ICON_NAME: 954 | case PROP_MAIN_ICON_PIXBUF: 955 | signal = "NewIcon"; 956 | break; 957 | case PROP_ATTENTION_ICON_NAME: 958 | case PROP_ATTENTION_ICON_PIXBUF: 959 | signal = "NewAttentionIcon"; 960 | break; 961 | case PROP_OVERLAY_ICON_NAME: 962 | case PROP_OVERLAY_ICON_PIXBUF: 963 | signal = "NewOverlayIcon"; 964 | break; 965 | case PROP_TOOLTIP_TITLE: 966 | case PROP_TOOLTIP_BODY: 967 | case PROP_TOOLTIP_ICON_NAME: 968 | case PROP_TOOLTIP_ICON_PIXBUF: 969 | signal = "NewToolTip"; 970 | break; 971 | default: 972 | g_return_if_reached (); 973 | } 974 | 975 | g_dbus_connection_emit_signal (priv->dbus_conn, 976 | NULL, 977 | ITEM_OBJECT, 978 | ITEM_INTERFACE, 979 | signal, 980 | NULL, 981 | NULL); 982 | } 983 | 984 | /** 985 | * status_notifier_item_new_from_pixbuf: 986 | * @id: The application id 987 | * @category: The category for the item 988 | * @pixbuf: The icon to use as main icon 989 | * 990 | * Creates a new item 991 | * 992 | * Returns: (transfer full): A new #StatusNotifierItem 993 | */ 994 | StatusNotifierItem * 995 | status_notifier_item_new_from_pixbuf (const gchar *id, 996 | StatusNotifierCategory category, 997 | GdkPixbuf *pixbuf) 998 | { 999 | return (StatusNotifierItem *) g_object_new (STATUS_NOTIFIER_TYPE_ITEM, 1000 | "id", id, 1001 | "category", category, 1002 | "main-icon-pixbuf", pixbuf, 1003 | NULL); 1004 | } 1005 | 1006 | /** 1007 | * status_notifier_item_new_from_icon_name: 1008 | * @id: The application id 1009 | * @category: The category for the item 1010 | * @icon_name: The name of the icon to use as main icon 1011 | * 1012 | * Creates a new item 1013 | * 1014 | * Returns: (transfer full): A new #StatusNotifierItem 1015 | */ 1016 | StatusNotifierItem * 1017 | status_notifier_item_new_from_icon_name (const gchar *id, 1018 | StatusNotifierCategory category, 1019 | const gchar *icon_name) 1020 | { 1021 | return (StatusNotifierItem *) g_object_new (STATUS_NOTIFIER_TYPE_ITEM, 1022 | "id", id, 1023 | "category", category, 1024 | "main-icon-name", icon_name, 1025 | NULL); 1026 | } 1027 | 1028 | /** 1029 | * status_notifier_item_get_id: 1030 | * @sn: A #StatusNotifierItem 1031 | * 1032 | * Returns the application id of @sn 1033 | * 1034 | * Returns: The application id of @sn. The string is owned by @sn, you should 1035 | * not free it 1036 | */ 1037 | const gchar * 1038 | status_notifier_item_get_id (StatusNotifierItem *sn) 1039 | { 1040 | g_return_val_if_fail (STATUS_NOTIFIER_IS_ITEM (sn), NULL); 1041 | return sn->priv->id; 1042 | } 1043 | 1044 | /** 1045 | * status_notifier_item_get_category: 1046 | * @sn: A #StatusNotifierItem 1047 | * 1048 | * Returns the category of @sn 1049 | * 1050 | * Returns: The category of @sn 1051 | */ 1052 | StatusNotifierCategory 1053 | status_notifier_item_get_category (StatusNotifierItem *sn) 1054 | { 1055 | g_return_val_if_fail (STATUS_NOTIFIER_IS_ITEM (sn), -1); 1056 | return sn->priv->category; 1057 | } 1058 | 1059 | /** 1060 | * status_notifier_item_set_from_pixbuf: 1061 | * @sn: A #StatusNotifierItem 1062 | * @icon: Which icon to set 1063 | * @pixbuf: A #GdkPixbuf to use for @icon 1064 | * 1065 | * Sets the icon @icon to @pixbuf. 1066 | * 1067 | * An icon can either be identified by its Freedesktop-compliant icon name, 1068 | * or by the icon data itself (via #GdkPixbuf). 1069 | * 1070 | * It is currently not possible to set both, as setting one will unset the 1071 | * other. 1072 | */ 1073 | void 1074 | status_notifier_item_set_from_pixbuf (StatusNotifierItem *sn, 1075 | StatusNotifierIcon icon, 1076 | GdkPixbuf *pixbuf) 1077 | { 1078 | StatusNotifierItemPrivate *priv; 1079 | 1080 | g_return_if_fail (STATUS_NOTIFIER_IS_ITEM (sn)); 1081 | priv = sn->priv; 1082 | 1083 | free_icon (sn, icon); 1084 | priv->icon[icon].has_pixbuf = TRUE; 1085 | priv->icon[icon].pixbuf = g_object_ref (pixbuf); 1086 | 1087 | notify (sn, prop_name_from_icon[icon]); 1088 | if (icon != STATUS_NOTIFIER_TOOLTIP_ICON || priv->tooltip_freeze == 0) 1089 | dbus_notify (sn, prop_name_from_icon[icon]); 1090 | } 1091 | 1092 | /** 1093 | * status_notifier_item_set_from_icon_name: 1094 | * @sn: A #StatusNotifierItem 1095 | * @icon: Which icon to set 1096 | * @icon_name: Name of an icon to use for @icon 1097 | * 1098 | * Sets the icon @icon to be @icon_name. 1099 | * 1100 | * An icon can either be identified by its Freedesktop-compliant icon name, 1101 | * or by the icon data itself (via #GdkPixbuf). 1102 | * 1103 | * It is currently not possible to set both, as setting one will unset the 1104 | * other. 1105 | */ 1106 | void 1107 | status_notifier_item_set_from_icon_name (StatusNotifierItem *sn, 1108 | StatusNotifierIcon icon, 1109 | const gchar *icon_name) 1110 | { 1111 | StatusNotifierItemPrivate *priv; 1112 | 1113 | g_return_if_fail (STATUS_NOTIFIER_IS_ITEM (sn)); 1114 | priv = sn->priv; 1115 | 1116 | free_icon (sn, icon); 1117 | priv->icon[icon].icon_name = g_strdup (icon_name); 1118 | 1119 | notify (sn, prop_pixbuf_from_icon[icon]); 1120 | if (icon != STATUS_NOTIFIER_TOOLTIP_ICON || priv->tooltip_freeze == 0) 1121 | dbus_notify (sn, prop_name_from_icon[icon]); 1122 | } 1123 | 1124 | /** 1125 | * status_notifier_item_has_pixbuf: 1126 | * @sn: A #StatusNotifierItem 1127 | * @icon: Which icon 1128 | * 1129 | * Returns whether icon @icon currently has a #GdkPixbuf set or not. If so, the 1130 | * icon data will be sent via DBus, else the icon name (if any) will be used. 1131 | * 1132 | * Returns: %TRUE is a #GdkPixbuf is set for @icon, else %FALSE 1133 | */ 1134 | gboolean 1135 | status_notifier_item_has_pixbuf (StatusNotifierItem *sn, 1136 | StatusNotifierIcon icon) 1137 | { 1138 | g_return_val_if_fail (STATUS_NOTIFIER_IS_ITEM (sn), FALSE); 1139 | return sn->priv->icon[icon].has_pixbuf; 1140 | } 1141 | 1142 | /** 1143 | * status_notifier_item_get_pixbuf: 1144 | * @sn: A #StatusNotifierItem 1145 | * @icon: The icon to get 1146 | * 1147 | * Returns the #GdkPixbuf set for @icon, if there's one. Not that it will return 1148 | * %NULL if an icon name is set. 1149 | * 1150 | * Returns: (transfer full): The #GdkPixbuf set for @icon, or %NULL 1151 | */ 1152 | GdkPixbuf * 1153 | status_notifier_item_get_pixbuf (StatusNotifierItem *sn, 1154 | StatusNotifierIcon icon) 1155 | { 1156 | StatusNotifierItemPrivate *priv; 1157 | 1158 | g_return_val_if_fail (STATUS_NOTIFIER_IS_ITEM (sn), NULL); 1159 | priv = sn->priv; 1160 | 1161 | if (!priv->icon[icon].has_pixbuf) 1162 | return NULL; 1163 | 1164 | return g_object_ref (priv->icon[icon].pixbuf); 1165 | } 1166 | 1167 | /** 1168 | * status_notifier_item_get_icon_name: 1169 | * @sn: A #StatusNotifierItem 1170 | * @icon: The icon to get 1171 | * 1172 | * Returns the icon name set for @icon, if there's one. Not that it will return 1173 | * %NULL if a #GdkPixbuf is set. 1174 | * 1175 | * Returns: (transfer full): A newly allocated string of the icon name set for 1176 | * @icon, free using g_free() 1177 | */ 1178 | gchar * 1179 | status_notifier_item_get_icon_name (StatusNotifierItem *sn, 1180 | StatusNotifierIcon icon) 1181 | { 1182 | StatusNotifierItemPrivate *priv; 1183 | 1184 | g_return_val_if_fail (STATUS_NOTIFIER_IS_ITEM (sn), NULL); 1185 | priv = sn->priv; 1186 | 1187 | if (priv->icon[icon].has_pixbuf) 1188 | return NULL; 1189 | 1190 | return g_strdup (priv->icon[icon].icon_name); 1191 | } 1192 | 1193 | /** 1194 | * status_notifier_item_set_attention_movie_name: 1195 | * @sn: A #StatusNotifierItem 1196 | * @movie_name: The name of the movie 1197 | * 1198 | * In addition to the icon, the item can also specify an animation associated to 1199 | * the #STATUS_NOTIFIER_STATUS_NEEDS_ATTENTION status. 1200 | * 1201 | * This should be either a Freedesktop-compliant icon name or a full path. The 1202 | * visualization can chose between the movie or icon (or using neither of those) 1203 | * at its discretion. 1204 | */ 1205 | void 1206 | status_notifier_item_set_attention_movie_name (StatusNotifierItem *sn, 1207 | const gchar *movie_name) 1208 | { 1209 | StatusNotifierItemPrivate *priv; 1210 | 1211 | g_return_if_fail (STATUS_NOTIFIER_IS_ITEM (sn)); 1212 | priv = sn->priv; 1213 | 1214 | g_free (priv->attention_movie_name); 1215 | priv->attention_movie_name = g_strdup (movie_name); 1216 | 1217 | notify (sn, PROP_ATTENTION_MOVIE_NAME); 1218 | } 1219 | 1220 | /** 1221 | * status_notifier_item_get_attention_movie_name: 1222 | * @sn: A #StatusNotifierItem 1223 | * 1224 | * Returns the movie name set for animation associated with the 1225 | * #STATUS_NOTIFIER_STATUS_NEEDS_ATTENTION status 1226 | * 1227 | * Returns: A newly allocated string with the movie name, free using g_free() 1228 | * when done 1229 | */ 1230 | gchar * 1231 | status_notifier_item_get_attention_movie_name (StatusNotifierItem *sn) 1232 | { 1233 | g_return_val_if_fail (STATUS_NOTIFIER_IS_ITEM (sn), NULL); 1234 | return g_strdup (sn->priv->attention_movie_name); 1235 | } 1236 | 1237 | /** 1238 | * status_notifier_item_set_title: 1239 | * @sn: A #StatusNotifierItem 1240 | * @title: The title 1241 | * 1242 | * Sets the title of the item (might be used by visualization e.g. in menu of 1243 | * hidden items when #STATUS_NOTIFIER_STATUS_PASSIVE) 1244 | */ 1245 | void 1246 | status_notifier_item_set_title (StatusNotifierItem *sn, 1247 | const gchar *title) 1248 | { 1249 | StatusNotifierItemPrivate *priv; 1250 | 1251 | g_return_if_fail (STATUS_NOTIFIER_IS_ITEM (sn)); 1252 | priv = sn->priv; 1253 | 1254 | g_free (priv->title); 1255 | priv->title = g_strdup (title); 1256 | 1257 | notify (sn, PROP_TITLE); 1258 | dbus_notify (sn, PROP_TITLE); 1259 | } 1260 | 1261 | /** 1262 | * status_notifier_item_get_title: 1263 | * @sn: A #StatusNotifierItem 1264 | * 1265 | * Returns the title of the item 1266 | * 1267 | * Returns: A newly allocated string, free with g_free() when done 1268 | */ 1269 | gchar * 1270 | status_notifier_item_get_title (StatusNotifierItem *sn) 1271 | { 1272 | g_return_val_if_fail (STATUS_NOTIFIER_IS_ITEM (sn), NULL); 1273 | return g_strdup (sn->priv->title); 1274 | } 1275 | 1276 | /** 1277 | * status_notifier_item_set_status: 1278 | * @sn: A #StatusNotifierItem 1279 | * @status: The new status 1280 | * 1281 | * Sets the item status to @status, describing the status of this item or of the 1282 | * associated application. 1283 | */ 1284 | void 1285 | status_notifier_item_set_status (StatusNotifierItem *sn, 1286 | StatusNotifierStatus status) 1287 | { 1288 | StatusNotifierItemPrivate *priv; 1289 | 1290 | g_return_if_fail (STATUS_NOTIFIER_IS_ITEM (sn)); 1291 | priv = sn->priv; 1292 | 1293 | priv->status = status; 1294 | 1295 | notify (sn, PROP_STATUS); 1296 | dbus_notify (sn, PROP_STATUS); 1297 | } 1298 | 1299 | /** 1300 | * status_notifier_item_get_status: 1301 | * @sn: A #StatusNotifierItem 1302 | * 1303 | * Returns the status of @sn 1304 | * 1305 | * Returns: Current status of @sn 1306 | */ 1307 | StatusNotifierStatus 1308 | status_notifier_item_get_status (StatusNotifierItem *sn) 1309 | { 1310 | g_return_val_if_fail (STATUS_NOTIFIER_IS_ITEM (sn), -1); 1311 | return sn->priv->status; 1312 | } 1313 | 1314 | /** 1315 | * status_notifier_item_set_window_id: 1316 | * @sn: A #StatusNotifierItem 1317 | * @window_id: The window ID 1318 | * 1319 | * Sets the window ID for @sn 1320 | * 1321 | * It's the windowing-system dependent identifier for a window, the application 1322 | * can chose one of its windows to be available trough this property or just set 1323 | * 0 if it's not interested. 1324 | */ 1325 | void 1326 | status_notifier_item_set_window_id (StatusNotifierItem *sn, 1327 | guint32 window_id) 1328 | { 1329 | StatusNotifierItemPrivate *priv; 1330 | 1331 | g_return_if_fail (STATUS_NOTIFIER_IS_ITEM (sn)); 1332 | priv = sn->priv; 1333 | 1334 | priv->window_id = window_id; 1335 | 1336 | notify (sn, PROP_WINDOW_ID); 1337 | } 1338 | 1339 | /** 1340 | * status_notifier_item_get_window_id: 1341 | * @sn: A #StatusNotifierItem 1342 | * 1343 | * Returns the windowing-system dependent idnetifier for a window associated 1344 | * with @sn 1345 | * 1346 | * Returns: The window ID associated with @sn 1347 | */ 1348 | guint32 1349 | status_notifier_item_get_window_id (StatusNotifierItem *sn) 1350 | { 1351 | g_return_val_if_fail (STATUS_NOTIFIER_IS_ITEM (sn), 0); 1352 | return sn->priv->window_id; 1353 | } 1354 | 1355 | /** 1356 | * status_notifier_item_freeze_tooltip: 1357 | * @sn:A #StatusNotifierItem 1358 | * 1359 | * Increases the freeze count for tooltip on @sn. If the freeze count is 1360 | * non-zero, the emission of a DBus signal for StatusNotifierHost to refresh the 1361 | * ToolTip property will be blocked until the freeze count drops back to zero 1362 | * (via status_notifier_item_thaw_tooltip()) 1363 | * 1364 | * This is to allow to set the different properties forming the tooltip (title, 1365 | * body and icon) without triggering a refresh afetr each change (as there is a 1366 | * single property ToolTip on the DBus item, with all data). 1367 | * 1368 | * Every call to status_notifier_item_freeze_tooltip() should later be followed by a 1369 | * call to status_notifier_item_thaw_tooltip() 1370 | */ 1371 | void 1372 | status_notifier_item_freeze_tooltip (StatusNotifierItem *sn) 1373 | { 1374 | g_return_if_fail (STATUS_NOTIFIER_IS_ITEM (sn)); 1375 | ++sn->priv->tooltip_freeze; 1376 | } 1377 | 1378 | /** 1379 | * status_notifier_item_thaw_tooltip: 1380 | * @sn: A #StatusNotifierItem 1381 | * 1382 | * Reverts the effect of a previous call to status_notifier_item_freeze_tooltip(). If 1383 | * the freeze count drops back to zero, a signal NewToolTip will be emitted on 1384 | * the DBus object for @sn, for StatusNotifierHost to refresh its ToolTip 1385 | * property. 1386 | * 1387 | * It is an error to call this function when the freeze count is zero. 1388 | */ 1389 | void 1390 | status_notifier_item_thaw_tooltip (StatusNotifierItem *sn) 1391 | { 1392 | StatusNotifierItemPrivate *priv; 1393 | 1394 | g_return_if_fail (STATUS_NOTIFIER_IS_ITEM (sn)); 1395 | priv = sn->priv; 1396 | g_return_if_fail (priv->tooltip_freeze > 0); 1397 | 1398 | if (--priv->tooltip_freeze == 0) 1399 | dbus_notify (sn, PROP_TOOLTIP_TITLE); 1400 | } 1401 | 1402 | /** 1403 | * status_notifier_item_set_tooltip: 1404 | * @sn: A #StatusNotifierItem 1405 | * @icon_name: The icon name to be used for #STATUS_NOTIFIER_TOOLTIP_ICON 1406 | * @title: The title of the tooltip 1407 | * @body: The body of the tooltip 1408 | * 1409 | * This is an helper function that allows to set icon name, title and body of 1410 | * the tooltip and then emit one DBus signal NewToolTip. 1411 | * 1412 | * It is equivalent to the following code, and similar code can be used e.g. to 1413 | * set the icon from a #GdkPixbuf instead: 1414 | * 1415 | * status_notifier_item_freeze_tooltip (sn); 1416 | * status_notifier_item_set_from_icon_name (sn, STATUS_NOTIFIER_TOOLTIP_ICON, icon_name); 1417 | * status_notifier_item_set_tooltip_title (sn, title); 1418 | * status_notifier_item_set_tooltip_body (sn, body); 1419 | * status_notifier_item_thaw_tooltip (sn); 1420 | * 1421 | */ 1422 | void 1423 | status_notifier_item_set_tooltip (StatusNotifierItem *sn, 1424 | const gchar *icon_name, 1425 | const gchar *title, 1426 | const gchar *body) 1427 | { 1428 | StatusNotifierItemPrivate *priv; 1429 | 1430 | g_return_if_fail (STATUS_NOTIFIER_IS_ITEM (sn)); 1431 | priv = sn->priv; 1432 | 1433 | ++priv->tooltip_freeze; 1434 | status_notifier_item_set_from_icon_name (sn, STATUS_NOTIFIER_TOOLTIP_ICON, icon_name); 1435 | status_notifier_item_set_tooltip_title (sn, title); 1436 | status_notifier_item_set_tooltip_body (sn, body); 1437 | status_notifier_item_thaw_tooltip (sn); 1438 | } 1439 | 1440 | /** 1441 | * status_notifier_item_set_tooltip_title: 1442 | * @sn: A #StatusNotifierItem 1443 | * @title: The tooltip title 1444 | * 1445 | * Sets the title of the tooltip 1446 | * 1447 | * The tooltip is composed of a title, a body, and an icon. Note that changing 1448 | * any of these will trigger a DBus signal NewToolTip (for hosts to refresh DBus 1449 | * property ToolTip), see status_notifier_item_freeze_tooltip() for changing more 1450 | * than one and only emitting one DBus signal at the end. 1451 | */ 1452 | void 1453 | status_notifier_item_set_tooltip_title (StatusNotifierItem *sn, 1454 | const gchar *title) 1455 | { 1456 | StatusNotifierItemPrivate *priv; 1457 | 1458 | g_return_if_fail (STATUS_NOTIFIER_IS_ITEM (sn)); 1459 | priv = sn->priv; 1460 | 1461 | g_free (priv->tooltip_title); 1462 | priv->tooltip_title = g_strdup (title); 1463 | 1464 | notify (sn, PROP_TOOLTIP_TITLE); 1465 | if (priv->tooltip_freeze == 0) 1466 | dbus_notify (sn, PROP_TOOLTIP_TITLE); 1467 | } 1468 | 1469 | /** 1470 | * status_notifier_item_get_tooltip_title: 1471 | * @sn: A #StatusNotifierItem 1472 | * 1473 | * Returns the tooltip title 1474 | * 1475 | * Returns: A newly allocated string of the tooltip title, use g_free() when 1476 | * done 1477 | */ 1478 | gchar * 1479 | status_notifier_item_get_tooltip_title (StatusNotifierItem *sn) 1480 | { 1481 | g_return_val_if_fail (STATUS_NOTIFIER_IS_ITEM (sn), NULL); 1482 | return g_strdup (sn->priv->tooltip_title); 1483 | } 1484 | 1485 | /** 1486 | * status_notifier_item_set_tooltip_body: 1487 | * @sn: A #StatusNotifierItem 1488 | * @body: The tooltip body 1489 | * 1490 | * Sets the body of the tooltip 1491 | * 1492 | * This body can contain some markup, which consists of a small subset of XHTML. 1493 | * See http://www.notmart.org/misc/statusnotifieritem/markup.html for more. 1494 | * 1495 | * The tooltip is composed of a title, a body, and an icon. Note that changing 1496 | * any of these will trigger a DBus signal NewToolTip (for hosts to refresh DBus 1497 | * property ToolTip), see status_notifier_item_freeze_tooltip() for changing more 1498 | * than one and only emitting one DBus signal at the end. 1499 | */ 1500 | void 1501 | status_notifier_item_set_tooltip_body (StatusNotifierItem *sn, 1502 | const gchar *body) 1503 | { 1504 | StatusNotifierItemPrivate *priv; 1505 | 1506 | g_return_if_fail (STATUS_NOTIFIER_IS_ITEM (sn)); 1507 | priv = sn->priv; 1508 | 1509 | g_free (priv->tooltip_body); 1510 | priv->tooltip_body = g_strdup (body); 1511 | 1512 | notify (sn, PROP_TOOLTIP_BODY); 1513 | if (priv->tooltip_freeze == 0) 1514 | dbus_notify (sn, PROP_TOOLTIP_BODY); 1515 | } 1516 | 1517 | /** 1518 | * status_notifier_item_get_tooltip_body: 1519 | * @sn: A #StatusNotifierItem 1520 | * 1521 | * Returns the tooltip body 1522 | * 1523 | * Returns: A newly allocated string of the tooltip body, use g_free() when done 1524 | */ 1525 | gchar * 1526 | status_notifier_item_get_tooltip_body (StatusNotifierItem *sn) 1527 | { 1528 | g_return_val_if_fail (STATUS_NOTIFIER_IS_ITEM (sn), NULL); 1529 | return g_strdup (sn->priv->tooltip_body); 1530 | } 1531 | 1532 | static void 1533 | method_call (GDBusConnection *conn _UNUSED_, 1534 | const gchar *sender _UNUSED_, 1535 | const gchar *object _UNUSED_, 1536 | const gchar *interface _UNUSED_, 1537 | const gchar *method, 1538 | GVariant *params, 1539 | GDBusMethodInvocation *invocation, 1540 | gpointer data) 1541 | { 1542 | StatusNotifierItem *sn = (StatusNotifierItem *) data; 1543 | guint signal; 1544 | gint x, y; 1545 | gboolean ret; 1546 | 1547 | if (!g_strcmp0 (method, "ContextMenu")) 1548 | signal = SIGNAL_CONTEXT_MENU; 1549 | else if (!g_strcmp0 (method, "Activate")) 1550 | signal = SIGNAL_ACTIVATE; 1551 | else if (!g_strcmp0 (method, "SecondaryActivate")) 1552 | signal = SIGNAL_SECONDARY_ACTIVATE; 1553 | else if (!g_strcmp0 (method, "Scroll")) 1554 | { 1555 | gint delta, orientation; 1556 | gchar *s_orientation; 1557 | 1558 | g_variant_get (params, "(is)", &delta, &s_orientation); 1559 | if (!g_ascii_strcasecmp (s_orientation, "vertical")) 1560 | orientation = STATUS_NOTIFIER_SCROLL_ORIENTATION_VERTICAL; 1561 | else 1562 | orientation = STATUS_NOTIFIER_SCROLL_ORIENTATION_HORIZONTAL; 1563 | g_free (s_orientation); 1564 | 1565 | g_signal_emit (sn, status_notifier_item_signals[SIGNAL_SCROLL], 0, 1566 | delta, orientation, &ret); 1567 | g_dbus_method_invocation_return_value (invocation, NULL); 1568 | return; 1569 | } 1570 | else 1571 | /* should never happen */ 1572 | g_return_if_reached (); 1573 | 1574 | g_variant_get (params, "(ii)", &x, &y); 1575 | g_signal_emit (sn, status_notifier_item_signals[signal], 0, x, y, &ret); 1576 | g_dbus_method_invocation_return_value (invocation, NULL); 1577 | } 1578 | 1579 | static GVariantBuilder * 1580 | get_builder_for_icon_pixmap (StatusNotifierItem *sn, StatusNotifierIcon icon) 1581 | { 1582 | StatusNotifierItemPrivate *priv = sn->priv; 1583 | GVariantBuilder *builder; 1584 | cairo_surface_t *surface; 1585 | cairo_t *cr; 1586 | gint width, height, stride; 1587 | guint *data; 1588 | 1589 | if (G_UNLIKELY (!priv->icon[icon].has_pixbuf)) 1590 | return NULL; 1591 | 1592 | width = gdk_pixbuf_get_width (priv->icon[icon].pixbuf); 1593 | height = gdk_pixbuf_get_height (priv->icon[icon].pixbuf); 1594 | 1595 | surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); 1596 | cr = cairo_create (surface); 1597 | gdk_cairo_set_source_pixbuf (cr, priv->icon[icon].pixbuf, 0, 0); 1598 | cairo_paint (cr); 1599 | cairo_destroy (cr); 1600 | 1601 | stride = cairo_image_surface_get_stride (surface); 1602 | cairo_surface_flush (surface); 1603 | data = (guint *) cairo_image_surface_get_data (surface); 1604 | #if G_BYTE_ORDER == G_LITTLE_ENDIAN 1605 | guint i, max; 1606 | 1607 | max = (guint) (stride * height) / sizeof (guint); 1608 | for (i = 0; i < max; ++i) 1609 | data[i] = GUINT_TO_BE (data[i]); 1610 | #endif 1611 | 1612 | builder = g_variant_builder_new (G_VARIANT_TYPE ("a(iiay)")); 1613 | g_variant_builder_open (builder, G_VARIANT_TYPE ("(iiay)")); 1614 | g_variant_builder_add (builder, "i", width); 1615 | g_variant_builder_add (builder, "i", height); 1616 | g_variant_builder_add_value (builder, 1617 | g_variant_new_from_data (G_VARIANT_TYPE ("ay"), 1618 | data, 1619 | (gsize) (stride * height), 1620 | TRUE, 1621 | (GDestroyNotify) cairo_surface_destroy, 1622 | surface)); 1623 | g_variant_builder_close (builder); 1624 | return builder; 1625 | } 1626 | 1627 | static GVariant * 1628 | get_prop (GDBusConnection *conn _UNUSED_, 1629 | const gchar *sender _UNUSED_, 1630 | const gchar *object _UNUSED_, 1631 | const gchar *interface _UNUSED_, 1632 | const gchar *property, 1633 | GError **error _UNUSED_, 1634 | gpointer data) 1635 | { 1636 | StatusNotifierItem *sn = (StatusNotifierItem *) data; 1637 | StatusNotifierItemPrivate *priv = sn->priv; 1638 | 1639 | if (!g_strcmp0 (property, "Id")) 1640 | return g_variant_new ("s", priv->id); 1641 | else if (!g_strcmp0 (property, "Category")) 1642 | { 1643 | const gchar const *s_category[] = { 1644 | "ApplicationStatus", 1645 | "Communications", 1646 | "SystemServices", 1647 | "Hardware" 1648 | }; 1649 | return g_variant_new ("s", s_category[priv->category]); 1650 | } 1651 | else if (!g_strcmp0 (property, "Title")) 1652 | return g_variant_new ("s", (priv->title) ? priv->title : ""); 1653 | else if (!g_strcmp0 (property, "Status")) 1654 | { 1655 | const gchar const *s_status[] = { 1656 | "Passive", 1657 | "Active", 1658 | "NeedsAttention" 1659 | }; 1660 | return g_variant_new ("s", s_status[priv->status]); 1661 | } 1662 | else if (!g_strcmp0 (property, "WindowId")) 1663 | return g_variant_new ("i", priv->window_id); 1664 | else if (!g_strcmp0 (property, "IconName")) 1665 | return g_variant_new ("s", (!priv->icon[STATUS_NOTIFIER_ICON].has_pixbuf) 1666 | ? ((priv->icon[STATUS_NOTIFIER_ICON].icon_name) 1667 | ? priv->icon[STATUS_NOTIFIER_ICON].icon_name : "") : ""); 1668 | else if (!g_strcmp0 (property, "IconPixmap")) 1669 | return g_variant_new ("a(iiay)", 1670 | get_builder_for_icon_pixmap (sn, STATUS_NOTIFIER_ICON)); 1671 | else if (!g_strcmp0 (property, "OverlayIconName")) 1672 | return g_variant_new ("s", (!priv->icon[STATUS_NOTIFIER_OVERLAY_ICON].has_pixbuf) 1673 | ? ((priv->icon[STATUS_NOTIFIER_OVERLAY_ICON].icon_name) 1674 | ? priv->icon[STATUS_NOTIFIER_OVERLAY_ICON].icon_name : "") : ""); 1675 | else if (!g_strcmp0 (property, "OverlayIconPixmap")) 1676 | return g_variant_new ("a(iiay)", 1677 | get_builder_for_icon_pixmap (sn, STATUS_NOTIFIER_OVERLAY_ICON)); 1678 | else if (!g_strcmp0 (property, "AttentionIconName")) 1679 | return g_variant_new ("s", (!priv->icon[STATUS_NOTIFIER_ATTENTION_ICON].has_pixbuf) 1680 | ? ((priv->icon[STATUS_NOTIFIER_ATTENTION_ICON].icon_name) 1681 | ? priv->icon[STATUS_NOTIFIER_ATTENTION_ICON].icon_name : "") : ""); 1682 | else if (!g_strcmp0 (property, "AttentionIconPixmap")) 1683 | return g_variant_new ("a(iiay)", 1684 | get_builder_for_icon_pixmap (sn, STATUS_NOTIFIER_ATTENTION_ICON)); 1685 | else if (!g_strcmp0 (property, "AttentionMovieName")) 1686 | return g_variant_new ("s", (priv->attention_movie_name) 1687 | ? priv->attention_movie_name : ""); 1688 | else if (!g_strcmp0 (property, "ToolTip")) 1689 | { 1690 | GVariant *variant; 1691 | GVariantBuilder *builder; 1692 | 1693 | if (!priv->icon[STATUS_NOTIFIER_TOOLTIP_ICON].has_pixbuf) 1694 | { 1695 | variant = g_variant_new ("(sa(iiay)ss)", 1696 | (priv->icon[STATUS_NOTIFIER_TOOLTIP_ICON].icon_name) 1697 | ? priv->icon[STATUS_NOTIFIER_TOOLTIP_ICON].icon_name : "", 1698 | NULL, 1699 | (priv->tooltip_title) ? priv->tooltip_title : "", 1700 | (priv->tooltip_body) ? priv->tooltip_body : ""); 1701 | return variant; 1702 | } 1703 | 1704 | builder = get_builder_for_icon_pixmap (sn, STATUS_NOTIFIER_TOOLTIP_ICON); 1705 | variant = g_variant_new ("(sa(iiay)ss)", 1706 | "", 1707 | builder, 1708 | (priv->tooltip_title) ? priv->tooltip_title : "", 1709 | (priv->tooltip_body) ? priv->tooltip_body : ""); 1710 | g_variant_builder_unref (builder); 1711 | 1712 | return variant; 1713 | } 1714 | else if (!g_strcmp0 (property, "ItemIsMenu")) 1715 | return g_variant_new ("b", priv->item_is_menu); 1716 | else if (!g_strcmp0 (property, "Menu")) 1717 | { 1718 | #if USE_DBUSMENU 1719 | if (priv->menu_service != NULL) 1720 | { 1721 | GValue strval = { 0 }; 1722 | GVariant *var; 1723 | 1724 | g_value_init (&strval, G_TYPE_STRING); 1725 | g_object_get_property (G_OBJECT (priv->menu_service), 1726 | DBUSMENU_SERVER_PROP_DBUS_OBJECT, &strval); 1727 | var = g_variant_new ("o", g_value_get_string (&strval)); 1728 | g_value_unset (&strval); 1729 | return var; 1730 | } 1731 | else 1732 | #endif 1733 | return g_variant_new ("o", "/NO_DBUSMENU"); 1734 | } 1735 | 1736 | g_return_val_if_reached (NULL); 1737 | } 1738 | 1739 | static void 1740 | dbus_failed (StatusNotifierItem *sn, GError *error, gboolean fatal) 1741 | { 1742 | StatusNotifierItemPrivate *priv = sn->priv; 1743 | 1744 | dbus_free (sn); 1745 | if (fatal) 1746 | { 1747 | priv->state = STATUS_NOTIFIER_STATE_FAILED; 1748 | notify (sn, PROP_STATE); 1749 | } 1750 | g_signal_emit (sn, status_notifier_item_signals[SIGNAL_REGISTRATION_FAILED], 0, 1751 | error); 1752 | g_error_free (error); 1753 | } 1754 | 1755 | static void 1756 | bus_acquired (GDBusConnection *conn, const gchar *name _UNUSED_, gpointer data) 1757 | { 1758 | GError *err = NULL; 1759 | StatusNotifierItem *sn = (StatusNotifierItem *) data; 1760 | StatusNotifierItemPrivate *priv = sn->priv; 1761 | GDBusInterfaceVTable interface_vtable = { 1762 | .method_call = method_call, 1763 | .get_property = get_prop, 1764 | .set_property = NULL 1765 | }; 1766 | GDBusNodeInfo *info; 1767 | 1768 | info = g_dbus_node_info_new_for_xml (item_xml, NULL); 1769 | priv->dbus_reg_id = g_dbus_connection_register_object (conn, 1770 | ITEM_OBJECT, 1771 | info->interfaces[0], 1772 | &interface_vtable, 1773 | sn, NULL, 1774 | &err); 1775 | g_dbus_node_info_unref (info); 1776 | if (priv->dbus_reg_id == 0) 1777 | { 1778 | dbus_failed (sn, err, TRUE); 1779 | return; 1780 | } 1781 | 1782 | priv->dbus_conn = g_object_ref (conn); 1783 | } 1784 | 1785 | static void 1786 | register_item_cb (GObject *sce, GAsyncResult *result, gpointer data) 1787 | { 1788 | GError *err = NULL; 1789 | StatusNotifierItem *sn = (StatusNotifierItem *) data; 1790 | StatusNotifierItemPrivate *priv = sn->priv; 1791 | GVariant *variant; 1792 | 1793 | variant = g_dbus_proxy_call_finish ((GDBusProxy *) sce, result, &err); 1794 | if (!variant) 1795 | { 1796 | dbus_failed (sn, err, TRUE); 1797 | return; 1798 | } 1799 | g_variant_unref (variant); 1800 | 1801 | priv->state = STATUS_NOTIFIER_STATE_REGISTERED; 1802 | notify (sn, PROP_STATE); 1803 | } 1804 | 1805 | static void 1806 | name_acquired (GDBusConnection *conn _UNUSED_, const gchar *name, gpointer data) 1807 | { 1808 | StatusNotifierItem *sn = (StatusNotifierItem *) data; 1809 | StatusNotifierItemPrivate *priv = sn->priv; 1810 | 1811 | g_dbus_proxy_call (priv->dbus_proxy, 1812 | "RegisterStatusNotifierItem", 1813 | g_variant_new ("(s)", name), 1814 | G_DBUS_CALL_FLAGS_NONE, 1815 | -1, 1816 | NULL, 1817 | register_item_cb, 1818 | sn); 1819 | g_object_unref (priv->dbus_proxy); 1820 | priv->dbus_proxy = NULL; 1821 | } 1822 | 1823 | static void 1824 | name_lost (GDBusConnection *conn, const gchar *name _UNUSED_, gpointer data) 1825 | { 1826 | GError *err = NULL; 1827 | StatusNotifierItem *sn = (StatusNotifierItem *) data; 1828 | 1829 | if (!conn) 1830 | g_set_error (&err, STATUS_NOTIFIER_ERROR, 1831 | STATUS_NOTIFIER_ERROR_NO_CONNECTION, 1832 | "Failed to establish DBus connection"); 1833 | else 1834 | g_set_error (&err, STATUS_NOTIFIER_ERROR, 1835 | STATUS_NOTIFIER_ERROR_NO_NAME, 1836 | "Failed to acquire name for item"); 1837 | dbus_failed (sn, err, TRUE); 1838 | } 1839 | 1840 | static void 1841 | dbus_reg_item (StatusNotifierItem *sn) 1842 | { 1843 | StatusNotifierItemPrivate *priv = sn->priv; 1844 | gchar buf[64], *b = buf; 1845 | 1846 | if (G_UNLIKELY (g_snprintf (buf, 64, "org.kde.StatusNotifierItem-%u-%u", 1847 | getpid (), ++uniq_id) >= 64)) 1848 | b = g_strdup_printf ("org.kde.StatusNotifierItem-%u-%u", 1849 | getpid (), uniq_id); 1850 | priv->dbus_owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, 1851 | b, 1852 | G_BUS_NAME_OWNER_FLAGS_NONE, 1853 | bus_acquired, 1854 | name_acquired, 1855 | name_lost, 1856 | sn, NULL); 1857 | if (G_UNLIKELY (b != buf)) 1858 | g_free (b); 1859 | } 1860 | 1861 | static void 1862 | watcher_signal (GDBusProxy *proxy _UNUSED_, 1863 | const gchar *sender _UNUSED_, 1864 | const gchar *signal, 1865 | GVariant *params _UNUSED_, 1866 | StatusNotifierItem *sn) 1867 | { 1868 | StatusNotifierItemPrivate *priv = sn->priv; 1869 | 1870 | if (!g_strcmp0 (signal, "StatusNotifierHostRegistered")) 1871 | { 1872 | g_signal_handler_disconnect (priv->dbus_proxy, priv->dbus_sid); 1873 | priv->dbus_sid = 0; 1874 | 1875 | dbus_reg_item (sn); 1876 | } 1877 | } 1878 | 1879 | static void 1880 | proxy_cb (GObject *sce _UNUSED_, GAsyncResult *result, gpointer data) 1881 | { 1882 | GError *err = NULL; 1883 | StatusNotifierItem *sn = (StatusNotifierItem *) data; 1884 | StatusNotifierItemPrivate *priv = sn->priv; 1885 | GVariant *variant; 1886 | 1887 | priv->dbus_proxy = g_dbus_proxy_new_for_bus_finish (result, &err); 1888 | if (!priv->dbus_proxy) 1889 | { 1890 | dbus_failed (sn, err, TRUE); 1891 | return; 1892 | } 1893 | 1894 | variant = g_dbus_proxy_get_cached_property (priv->dbus_proxy, 1895 | "IsStatusNotifierHostRegistered"); 1896 | if (!variant || !g_variant_get_boolean (variant)) 1897 | { 1898 | GDBusProxy *proxy; 1899 | 1900 | g_set_error (&err, STATUS_NOTIFIER_ERROR, 1901 | STATUS_NOTIFIER_ERROR_NO_HOST, 1902 | "No Host registered on the Watcher"); 1903 | if (variant) 1904 | g_variant_unref (variant); 1905 | 1906 | /* keep the proxy, we'll wait for the signal when a host registers */ 1907 | proxy = priv->dbus_proxy; 1908 | /* (so dbus_free() from dbus_failed() doesn't unref) */ 1909 | priv->dbus_proxy = NULL; 1910 | dbus_failed (sn, err, FALSE); 1911 | priv->dbus_proxy = proxy; 1912 | 1913 | priv->dbus_sid = g_signal_connect (priv->dbus_proxy, "g-signal", 1914 | (GCallback) watcher_signal, sn); 1915 | return; 1916 | } 1917 | g_variant_unref (variant); 1918 | 1919 | dbus_reg_item (sn); 1920 | } 1921 | 1922 | static void 1923 | watcher_appeared (GDBusConnection *conn _UNUSED_, 1924 | const gchar *name _UNUSED_, 1925 | const gchar *owner _UNUSED_, 1926 | gpointer data) 1927 | { 1928 | StatusNotifierItem *sn = data; 1929 | StatusNotifierItemPrivate *priv = sn->priv; 1930 | GDBusNodeInfo *info; 1931 | 1932 | g_bus_unwatch_name (priv->dbus_watch_id); 1933 | priv->dbus_watch_id = 0; 1934 | 1935 | info = g_dbus_node_info_new_for_xml (watcher_xml, NULL); 1936 | g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, 1937 | G_DBUS_PROXY_FLAGS_NONE, 1938 | info->interfaces[0], 1939 | WATCHER_NAME, 1940 | WATCHER_OBJECT, 1941 | WATCHER_INTERFACE, 1942 | NULL, 1943 | proxy_cb, 1944 | sn); 1945 | g_dbus_node_info_unref (info); 1946 | } 1947 | 1948 | static void 1949 | watcher_vanished (GDBusConnection *conn _UNUSED_, 1950 | const gchar *name _UNUSED_, 1951 | gpointer data) 1952 | { 1953 | GError *err = NULL; 1954 | StatusNotifierItem *sn = data; 1955 | StatusNotifierItemPrivate *priv = sn->priv; 1956 | guint id; 1957 | 1958 | /* keep the watch active, so if a watcher shows up we'll resume the 1959 | * registering automatically */ 1960 | id = priv->dbus_watch_id; 1961 | /* (so dbus_free() from dbus_failed() doesn't unwatch) */ 1962 | priv->dbus_watch_id = 0; 1963 | 1964 | g_set_error (&err, STATUS_NOTIFIER_ERROR, 1965 | STATUS_NOTIFIER_ERROR_NO_WATCHER, 1966 | "No Watcher found"); 1967 | dbus_failed (sn, err, FALSE); 1968 | 1969 | priv->dbus_watch_id = id; 1970 | } 1971 | 1972 | /** 1973 | * status_notifier_item_register: 1974 | * @sn: A #StatusNotifierItem 1975 | * 1976 | * Registers @sn to the StatusNotifierWatcher over DBus. 1977 | * 1978 | * Once you have created your #StatusNotifierItem you need to register it, so 1979 | * any host/visualization can use it and update their GUI as needed. 1980 | * 1981 | * This function will connect to the StatusNotifierWatcher and make sure at 1982 | * least one StatusNotifierHost is registered. Then, it will register a new 1983 | * StatusNotifierItem on the session bus and register it with the watcher. 1984 | * 1985 | * When done, property #StatusNotifierItem:state will change to 1986 | * %STATUS_NOTIFIER_STATE_REGISTERED. If something fails, signal 1987 | * #StatusNotifierItem::registration-failed will be emitted, at which point you 1988 | * should fallback to using the systray. 1989 | * 1990 | * However there are two possible types of failures: fatal and non-fatal ones. 1991 | * Fatal error means that #StatusNotifierItem:state will be 1992 | * %STATUS_NOTIFIER_STATE_FAILED and you can unref @sn. 1993 | * 1994 | * Non-fatal error means it will still be %STATUS_NOTIFIER_STATE_REGISTERING as 1995 | * the registration process could still eventually succeed. For example, if 1996 | * there was no host registered on the watcher, as soon as signal 1997 | * StatusNotifierHostRegistered is emitted on the watcher, the registration 1998 | * process for @sn will complete and #StatusNotifierItem:state set to 1999 | * %STATUS_NOTIFIER_STATE_REGISTERED, at which point you should stop using the 2000 | * systray. 2001 | * 2002 | * This also means it is possible to have multiple signals 2003 | * #StatusNotifierItem::registration-failed emitted on the same 2004 | * #StatusNotifierItem. 2005 | * 2006 | * Note that you can call status_notifier_item_register() after a fatal error 2007 | * occured, to try again. You can also unref @sn while it is 2008 | * %STATUS_NOTIFIER_STATE_REGISTERING safely. 2009 | */ 2010 | void 2011 | status_notifier_item_register (StatusNotifierItem *sn) 2012 | 2013 | { 2014 | StatusNotifierItemPrivate *priv; 2015 | 2016 | g_return_if_fail (STATUS_NOTIFIER_IS_ITEM (sn)); 2017 | priv = sn->priv; 2018 | 2019 | if (priv->state == STATUS_NOTIFIER_STATE_REGISTERING 2020 | || priv->state == STATUS_NOTIFIER_STATE_REGISTERED) 2021 | return; 2022 | priv->state = STATUS_NOTIFIER_STATE_REGISTERING; 2023 | 2024 | priv->dbus_watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION, 2025 | WATCHER_NAME, 2026 | G_BUS_NAME_WATCHER_FLAGS_AUTO_START, 2027 | watcher_appeared, 2028 | watcher_vanished, 2029 | sn, NULL); 2030 | } 2031 | 2032 | /** 2033 | * status_notifier_item_get_state: 2034 | * @sn: A #StatusNotifierItem 2035 | * 2036 | * Returns the DBus registration state of @sn. See 2037 | * status_notifier_item_register() for more. 2038 | * 2039 | * Returns: The DBus registration state of @sn 2040 | */ 2041 | StatusNotifierState 2042 | status_notifier_item_get_state (StatusNotifierItem *sn) 2043 | { 2044 | g_return_val_if_fail (STATUS_NOTIFIER_IS_ITEM (sn), FALSE); 2045 | return sn->priv->state; 2046 | } 2047 | 2048 | /** 2049 | * status_notifier_item_set_item_is_menu: 2050 | * @sn: A #StatusNotifierItem 2051 | * @is_menu: Whether or not @sn only supports context menu 2052 | * 2053 | * This is only an indication for the visualization (i.e. the 2054 | * StatusNotifierHost) as to how to handle user interactions. 2055 | * 2056 | * Specifically, if %TRUE it should prefer showing the menu (when set via 2057 | * #StatusNotifierItem:menu or status_notifier_item_set_context_menu()) or 2058 | * trigger #StatusNotifierItem::context-menu instead of 2059 | * #StatusNotifierItem::activate 2060 | * 2061 | * Since: 1.0.0 2062 | */ 2063 | void 2064 | status_notifier_item_set_item_is_menu (StatusNotifierItem *sn, 2065 | gboolean is_menu) 2066 | { 2067 | g_return_if_fail (STATUS_NOTIFIER_IS_ITEM (sn)); 2068 | sn->priv->item_is_menu = is_menu; 2069 | } 2070 | 2071 | /** 2072 | * status_notifier_item_get_item_is_menu: 2073 | * @sn: A #StatusNotifierItem 2074 | * 2075 | * Returns whether or not @sn only supports context menu. See 2076 | * status_notifier_item_set_item_is_menu() for more. 2077 | * 2078 | * Returns: Whether or not @sn only supports context menu 2079 | * 2080 | * Since: 1.0.0 2081 | */ 2082 | gboolean 2083 | status_notifier_item_get_item_is_menu (StatusNotifierItem *sn) 2084 | { 2085 | g_return_val_if_fail (STATUS_NOTIFIER_IS_ITEM (sn), FALSE); 2086 | return sn->priv->item_is_menu; 2087 | } 2088 | 2089 | /** 2090 | * status_notifier_item_set_context_menu: 2091 | * @sn: A #StatusNotifierItem 2092 | * @menu: (allow-none): A #GtkWidget of the menu to set as context menu or %NULL 2093 | * 2094 | * Exports specified context menu via dbus. 2095 | * If @menu is set, g_object_ref_sink() will be used to take ownership. 2096 | * Also note that no #StatusNotifierItem::context_menu signals will be emitted 2097 | * when a context menu is set/shared via DBus. 2098 | * If @menu is %NULL any current menu will be unset (and 2099 | * #StatusNotifierItem::context_menu signals will be emitted as needed again). 2100 | * 2101 | * Note that is dbusmenu support wasn't enabled during compilation, this 2102 | * function does nothing but returning %FALSE, thus allowing you to fallback on 2103 | * handling the #StatusNotifierItem::context_menu signal. 2104 | * 2105 | * Returns: %TRUE is dbusmenu support is available, else %FALSE 2106 | * 2107 | * Since: 1.0.0 2108 | */ 2109 | gboolean 2110 | status_notifier_item_set_context_menu (StatusNotifierItem *sn, 2111 | GObject *menu) 2112 | { 2113 | #if USE_DBUSMENU 2114 | StatusNotifierItemPrivate *priv; 2115 | DbusmenuMenuitem *root = NULL; 2116 | 2117 | g_return_val_if_fail (STATUS_NOTIFIER_IS_ITEM (sn), FALSE); 2118 | g_return_val_if_fail (!menu || GTK_IS_MENU (menu), FALSE); 2119 | priv = sn->priv; 2120 | 2121 | if (priv->menu) 2122 | g_object_unref (priv->menu); 2123 | 2124 | priv->menu = menu; 2125 | 2126 | if (menu) 2127 | { 2128 | g_object_ref_sink (priv->menu); 2129 | 2130 | root = dbusmenu_gtk_parse_menu_structure (GTK_WIDGET (priv->menu)); 2131 | 2132 | if (priv->menu_service == NULL) 2133 | priv->menu_service = dbusmenu_server_new ("/MenuBar"); 2134 | 2135 | dbusmenu_server_set_root (priv->menu_service, root); 2136 | 2137 | /* Drop our local ref as set_root should get it's own. */ 2138 | if (root != NULL) 2139 | g_object_unref (root); 2140 | } 2141 | else if (priv->menu_service) 2142 | { 2143 | g_object_unref (priv->menu_service); 2144 | priv->menu_service = NULL; 2145 | } 2146 | 2147 | return TRUE; 2148 | #else 2149 | return FALSE; 2150 | #endif 2151 | } 2152 | 2153 | /** 2154 | * status_notifier_item_get_context_menu: 2155 | * @sn: A #StatusNotifierItem 2156 | * 2157 | * Returns the #GtkWidget set as context menu, or %NULL 2158 | * 2159 | * Note that if dbusmenu support wasn't enabled during compilation it will 2160 | * always return %NULL. See status_notifier_item_set_context_menu() for how to 2161 | * check. 2162 | * 2163 | * Returns: (transfer none): #GtkWidget or %NULL (no menu set, or no support 2164 | * compiled in) 2165 | * 2166 | * Since: 1.0.0 2167 | */ 2168 | GObject * 2169 | status_notifier_item_get_context_menu (StatusNotifierItem *sn) 2170 | { 2171 | #if USE_DBUSMENU 2172 | StatusNotifierItemPrivate *priv; 2173 | 2174 | g_return_val_if_fail (STATUS_NOTIFIER_IS_ITEM (sn), NULL); 2175 | priv = sn->priv; 2176 | 2177 | return priv->menu; 2178 | #else 2179 | return NULL; 2180 | #endif 2181 | } 2182 | -------------------------------------------------------------------------------- /src/statusnotifier.h: -------------------------------------------------------------------------------- 1 | /* 2 | * statusnotifier - Copyright (C) 2014-2017 Olivier Brunel 3 | * 4 | * statusnotifier.h 5 | * Copyright (C) 2014-2017 Olivier Brunel 6 | * 7 | * This file is part of statusnotifier. 8 | * 9 | * statusnotifier is free software: you can redistribute it and/or modify it 10 | * under the terms of the GNU General Public License as published by the Free 11 | * Software Foundation, either version 3 of the License, or (at your option) any 12 | * later version. 13 | * 14 | * statusnotifier is distributed in the hope that it will be useful, but WITHOUT 15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 | * FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * statusnotifier. If not, see http://www.gnu.org/licenses/ 21 | */ 22 | 23 | #ifndef __STATUS_NOTIFIER_H__ 24 | #define __STATUS_NOTIFIER_H__ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | G_BEGIN_DECLS 32 | 33 | typedef struct _StatusNotifierItem StatusNotifierItem; 34 | typedef struct _StatusNotifierItemPrivate StatusNotifierItemPrivate; 35 | typedef struct _StatusNotifierItemClass StatusNotifierItemClass; 36 | 37 | #define STATUS_NOTIFIER_TYPE_ITEM (status_notifier_item_get_type ()) 38 | #define STATUS_NOTIFIER_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), STATUS_NOTIFIER_TYPE_ITEM, StatusNotifierItem)) 39 | #define STATUS_NOTIFIER_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), STATUS_NOTIFIER_TYPE_ITEM, StatusNotifierItemClass)) 40 | #define STATUS_NOTIFIER_IS_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), STATUS_NOTIFIER_TYPE_ITEM)) 41 | #define STATUS_NOTIFIER_IS_ITEM_CLASS(klass)(G_TYPE_CHECK_CLASS_TYPE ((obj), STATUS_NOTIFIER_TYPE_ITEM)) 42 | #define STATUS_NOTIFIER_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), STATUS_NOTIFIER_TYPE_ITEM, StatusNotifierItemClass)) 43 | 44 | GType status_notifier_item_get_type (void) G_GNUC_CONST; 45 | 46 | #define STATUS_NOTIFIER_ERROR g_quark_from_static_string ("StatusNotifier error") 47 | /** 48 | * StatusNotifierError: 49 | * @STATUS_NOTIFIER_ERROR_NO_CONNECTION: Failed to establish connection to 50 | * register service on session bus 51 | * @STATUS_NOTIFIER_ERROR_NO_NAME: Failed to acquire name for the item on the 52 | * session bus 53 | * @STATUS_NOTIFIER_ERROR_NO_WATCHER: No StatusNotifierWatcher found on the 54 | * session bus 55 | * @STATUS_NOTIFIER_ERROR_NO_HOST: No StatusNotifierHost registered with the 56 | * StatusNotifierWatcher 57 | * 58 | * Errors that can occur while trying to register the item. Note that errors 59 | * other the #StatusNotifierError might be returned. 60 | */ 61 | typedef enum 62 | { 63 | STATUS_NOTIFIER_ERROR_NO_CONNECTION = 0, 64 | STATUS_NOTIFIER_ERROR_NO_NAME, 65 | STATUS_NOTIFIER_ERROR_NO_WATCHER, 66 | STATUS_NOTIFIER_ERROR_NO_HOST 67 | } StatusNotifierError; 68 | 69 | /** 70 | * StatusNotifierState: 71 | * @STATUS_NOTIFIER_STATE_NOT_REGISTERED: Item hasn't yet been asked to 72 | * register, i.e. no call to status_notifier_item_register() have been made yet 73 | * @STATUS_NOTIFIER_STATE_REGISTERING: Item is in the process of registering. 74 | * This state is also valid after #StatusNotifierItem::registration-failed was 75 | * emitted, if the item is waiting for possible "recovery" (e.g. if no host was 76 | * registered on watcher, waiting for one to do so) 77 | * @STATUS_NOTIFIER_STATE_REGISTERED: Item was sucessfully registered on DBus 78 | * and StatusNotifierWatcher 79 | * @STATUS_NOTIFIER_STATE_FAILED: Registration failed, with no possible pending 80 | * recovery 81 | * 82 | * State in which a #StatusNotifierItem can be. See 83 | * status_notifier_item_register() for more 84 | */ 85 | typedef enum 86 | { 87 | STATUS_NOTIFIER_STATE_NOT_REGISTERED = 0, 88 | STATUS_NOTIFIER_STATE_REGISTERING, 89 | STATUS_NOTIFIER_STATE_REGISTERED, 90 | STATUS_NOTIFIER_STATE_FAILED 91 | } StatusNotifierState; 92 | 93 | /** 94 | * StatusNotifierIcon: 95 | * @STATUS_NOTIFIER_ICON: The icon that can be used by the visualization to 96 | * identify the item. 97 | * @STATUS_NOTIFIER_ATTENTION_ICON: The icon that can be used by the 98 | * visualization when the item's status is 99 | * %STATUS_NOTIFIER_STATUS_NEEDS_ATTENTION. 100 | * @STATUS_NOTIFIER_OVERLAY_ICON: This can be used by the visualization to 101 | * indicate extra state information, for instance as an overlay for the main 102 | * icon. 103 | * @STATUS_NOTIFIER_TOOLTIP_ICON: The icon that can be used be the visualization 104 | * in the tooltip of the item. 105 | * 106 | * Possible icons that can be used on a status notifier item. 107 | */ 108 | typedef enum 109 | { 110 | STATUS_NOTIFIER_ICON = 0, 111 | STATUS_NOTIFIER_ATTENTION_ICON, 112 | STATUS_NOTIFIER_OVERLAY_ICON, 113 | STATUS_NOTIFIER_TOOLTIP_ICON, 114 | /*< private >*/ 115 | _NB_STATUS_NOTIFIER_ICONS 116 | } StatusNotifierIcon; 117 | 118 | /** 119 | * StatusNotifierCategory: 120 | * @STATUS_NOTIFIER_CATEGORY_APPLICATION_STATUS: The item describes the status 121 | * of a generic application, for instance the current state of a media player. 122 | * In the case where the category of the item can not be known, such as when the 123 | * item is being proxied from another incompatible or emulated system, this can 124 | * be used a sensible default fallback. 125 | * @STATUS_NOTIFIER_CATEGORY_COMMUNICATIONS: The item describes the status of 126 | * communication oriented applications, like an instant messenger or an email 127 | * client. 128 | * @STATUS_NOTIFIER_CATEGORY_SYSTEM_SERVICES: The item describes services of the 129 | * system not seen as a stand alone application by the user, such as an 130 | * indicator for the activity of a disk indexing service. 131 | * @STATUS_NOTIFIER_CATEGORY_HARDWARE: The item describes the state and control 132 | * of a particular hardware, such as an indicator of the battery charge or sound 133 | * card volume control. 134 | * 135 | * The category of the status notifier item. 136 | */ 137 | typedef enum 138 | { 139 | STATUS_NOTIFIER_CATEGORY_APPLICATION_STATUS = 0, 140 | STATUS_NOTIFIER_CATEGORY_COMMUNICATIONS, 141 | STATUS_NOTIFIER_CATEGORY_SYSTEM_SERVICES, 142 | STATUS_NOTIFIER_CATEGORY_HARDWARE 143 | } StatusNotifierCategory; 144 | 145 | /** 146 | * StatusNotifierStatus: 147 | * @STATUS_NOTIFIER_STATUS_PASSIVE: The item doesn't convey important 148 | * information to the user, it can be considered an "idle" status and is likely 149 | * that visualizations will chose to hide it. 150 | * @STATUS_NOTIFIER_STATUS_ACTIVE: The item is active, is more important that 151 | * the item will be shown in some way to the user. 152 | * @STATUS_NOTIFIER_STATUS_NEEDS_ATTENTION: The item carries really important 153 | * information for the user, such as battery charge running out and is wants to 154 | * incentive the direct user intervention. Visualizations should emphasize in 155 | * some way the items with this status. 156 | * 157 | * The status of the status notifier item or its associated application. 158 | */ 159 | typedef enum 160 | { 161 | STATUS_NOTIFIER_STATUS_PASSIVE = 0, 162 | STATUS_NOTIFIER_STATUS_ACTIVE, 163 | STATUS_NOTIFIER_STATUS_NEEDS_ATTENTION 164 | } StatusNotifierStatus; 165 | 166 | /** 167 | * StatusNotifierScrollOrientation: 168 | * @STATUS_NOTIFIER_SCROLL_ORIENTATION_HORIZONTAL: Scroll request was 169 | * horizontal. 170 | * @STATUS_NOTIFIER_SCROLL_ORIENTATION_VERTICAL: Scroll request was vertical. 171 | * 172 | * The orientation of a scroll request performed on the representation of the 173 | * item in the visualization. 174 | */ 175 | typedef enum 176 | { 177 | STATUS_NOTIFIER_SCROLL_ORIENTATION_HORIZONTAL = 0, 178 | STATUS_NOTIFIER_SCROLL_ORIENTATION_VERTICAL 179 | } StatusNotifierScrollOrientation; 180 | 181 | struct _StatusNotifierItem 182 | { 183 | /*< private >*/ 184 | GObject parent; 185 | StatusNotifierItemPrivate *priv; 186 | }; 187 | 188 | /** 189 | * StatusNotifierItemClass: 190 | * @parent_class: Parent class 191 | * @registration_failed: When registering the item failed, e.g. because there's 192 | * no StatusNotifierHost registered (yet); If this occurs, you should fallback 193 | * to using the systray 194 | * @context_menu: Item should show a context menu, this is typically a 195 | * consequence of user input, such as mouse right click over the graphical 196 | * representation of the item. 197 | * @activate: Activation of the item was requested, this is typically a 198 | * consequence of user input, such as mouse left click over the graphical 199 | * representation of the item. 200 | * @secondary_activate: Secondary and less important form of activation 201 | * (compared to @activate) of the item was requested. This is typically a 202 | * consequence of user input, such as mouse middle click over the graphical 203 | * representation of the item. 204 | * @scroll: The user asked for a scroll action. This is caused from input such 205 | * as mouse wheel over the graphical representation of the item. 206 | */ 207 | struct _StatusNotifierItemClass 208 | { 209 | GObjectClass parent_class; 210 | 211 | /* signals */ 212 | void (*registration_failed) (StatusNotifierItem *sn, 213 | GError *error); 214 | 215 | gboolean (*context_menu) (StatusNotifierItem *sn, 216 | gint x, 217 | gint y); 218 | gboolean (*activate) (StatusNotifierItem *sn, 219 | gint x, 220 | gint y); 221 | gboolean (*secondary_activate) (StatusNotifierItem *sn, 222 | gint x, 223 | gint y); 224 | gboolean (*scroll) (StatusNotifierItem *sn, 225 | gint delta, 226 | StatusNotifierScrollOrientation orientation); 227 | }; 228 | 229 | StatusNotifierItem * status_notifier_item_new_from_pixbuf ( 230 | const gchar *id, 231 | StatusNotifierCategory category, 232 | GdkPixbuf *pixbuf); 233 | StatusNotifierItem * status_notifier_item_new_from_icon_name ( 234 | const gchar *id, 235 | StatusNotifierCategory category, 236 | const gchar *icon_name); 237 | const gchar * status_notifier_item_get_id ( 238 | StatusNotifierItem *sn); 239 | StatusNotifierCategory status_notifier_item_get_category ( 240 | StatusNotifierItem *sn); 241 | void status_notifier_item_set_from_pixbuf ( 242 | StatusNotifierItem *sn, 243 | StatusNotifierIcon icon, 244 | GdkPixbuf *pixbuf); 245 | void status_notifier_item_set_from_icon_name ( 246 | StatusNotifierItem *sn, 247 | StatusNotifierIcon icon, 248 | const gchar *icon_name); 249 | gboolean status_notifier_item_has_pixbuf ( 250 | StatusNotifierItem *sn, 251 | StatusNotifierIcon icon); 252 | GdkPixbuf * status_notifier_item_get_pixbuf ( 253 | StatusNotifierItem *sn, 254 | StatusNotifierIcon icon); 255 | gchar * status_notifier_item_get_icon_name ( 256 | StatusNotifierItem *sn, 257 | StatusNotifierIcon icon); 258 | void status_notifier_item_set_attention_movie_name ( 259 | StatusNotifierItem *sn, 260 | const gchar *movie_name); 261 | gchar * status_notifier_item_get_attention_movie_name ( 262 | StatusNotifierItem *sn); 263 | void status_notifier_item_set_title ( 264 | StatusNotifierItem *sn, 265 | const gchar *title); 266 | gchar * status_notifier_item_get_title ( 267 | StatusNotifierItem *sn); 268 | void status_notifier_item_set_status ( 269 | StatusNotifierItem *sn, 270 | StatusNotifierStatus status); 271 | StatusNotifierStatus status_notifier_item_get_status ( 272 | StatusNotifierItem *sn); 273 | void status_notifier_item_set_window_id ( 274 | StatusNotifierItem *sn, 275 | guint32 window_id); 276 | guint32 status_notifier_item_get_window_id ( 277 | StatusNotifierItem *sn); 278 | void status_notifier_item_freeze_tooltip ( 279 | StatusNotifierItem *sn); 280 | void status_notifier_item_thaw_tooltip ( 281 | StatusNotifierItem *sn); 282 | void status_notifier_item_set_tooltip ( 283 | StatusNotifierItem *sn, 284 | const gchar *icon_name, 285 | const gchar *title, 286 | const gchar *body); 287 | void status_notifier_item_set_tooltip_title ( 288 | StatusNotifierItem *sn, 289 | const gchar *title); 290 | gchar * status_notifier_item_get_tooltip_title ( 291 | StatusNotifierItem *sn); 292 | void status_notifier_item_set_tooltip_body ( 293 | StatusNotifierItem *sn, 294 | const gchar *body); 295 | gchar * status_notifier_item_get_tooltip_body ( 296 | StatusNotifierItem *sn); 297 | void status_notifier_item_register ( 298 | StatusNotifierItem *sn); 299 | StatusNotifierState status_notifier_item_get_state ( 300 | StatusNotifierItem *sn); 301 | void status_notifier_item_set_item_is_menu ( 302 | StatusNotifierItem *sn, 303 | gboolean is_menu); 304 | gboolean status_notifier_item_get_item_is_menu ( 305 | StatusNotifierItem *sn); 306 | gboolean status_notifier_item_set_context_menu ( 307 | StatusNotifierItem *sn, 308 | GObject *menu); 309 | GObject * status_notifier_item_get_context_menu ( 310 | StatusNotifierItem *sn); 311 | 312 | G_END_DECLS 313 | 314 | #endif /* __STATUS_NOTIFIER_H__ */ 315 | -------------------------------------------------------------------------------- /statusnotifier.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: StatusNotifier 7 | Description: Status Notifier Item Library 8 | Version: @VERSION@ 9 | Requires: @DEP_PACKAGES@ 10 | Libs: -L${libdir} -lstatusnotifier 11 | Cflags: -I${includedir} 12 | --------------------------------------------------------------------------------