├── .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 |
--------------------------------------------------------------------------------