pax_global_header 0000666 0000000 0000000 00000000064 13736457142 0014526 g ustar 00root root 0000000 0000000 52 comment=0b6d12fb4d902823049c36aac0068c2f377cede2
vala-panel-0.5.0/ 0000775 0000000 0000000 00000000000 13736457142 0013550 5 ustar 00root root 0000000 0000000 vala-panel-0.5.0/.clang-format 0000664 0000000 0000000 00000005034 13736457142 0016125 0 ustar 00root root 0000000 0000000 ---
AccessModifierOffset: 0
AlignAfterOpenBracket: true
AlignConsecutiveAssignments: true
#uncomment for clang 3.9
#AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: false
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
# AlwaysBreakAfterDefinitionReturnType: None
#uncomment for clang 3.9
#AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: false
BinPackArguments: false
BinPackParameters: true
# BraceWrapping: (not set since BreakBeforeBraces is not Custom)
BreakBeforeBinaryOperators: None
# BreakAfterJavaFieldAnnotations: (not java)
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Allman
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
#uncomment for clang 3.9
#BreakStringLiterals: false
ColumnLimit: 100
CommentPragmas: '\*\<'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
#Uncomment for clang 3.9
#IncludeCategories:
# - Regex: '^"'
# Priority: 1
# IncludeIsMainRegex: (project doesn't use a main includes that can add other includes via regex)
IndentCaseLabels: false
IndentWidth: 8
IndentWrappedFunctionNames: false
# JavaScriptQuotes: (not javascript)
KeepEmptyLinesAtTheStartOfBlocks: false
Language: Cpp
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
# ObjCBlockIndentWidth: (not objc)
# ObjCSpaceAfterProperty: (not objc)
# ObjCSpaceBeforeProtocolList: (not objc)
PenaltyBreakBeforeFirstCallParameter: 400
PenaltyBreakComment: 0
# PenaltyBreakFirstLessLess: (not cpp)
PenaltyBreakString: 500
PenaltyExcessCharacter: 10000
PenaltyReturnTypeOnItsOwnLine: 600
PointerAlignment: Right
#uncomment for clang 3.9
#ReflowComments: true
#uncomment for clang 3.9
#SortIncludes: true
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
# SpacesInContainerLiterals: (not objc or javascript)
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 8
UseTab: ForIndentation
...
vala-panel-0.5.0/.gitignore 0000664 0000000 0000000 00000000055 13736457142 0015540 0 ustar 00root root 0000000 0000000 vala-panel
build/
.vscode
CMakeLists.txt.user vala-panel-0.5.0/.gitlab-ci.yml 0000664 0000000 0000000 00000001365 13736457142 0016211 0 ustar 00root root 0000000 0000000 stages:
- build
- release
before_script:
- mkdir -p _ccache
- export CCACHE_BASEDIR=${PWD}
- export CCACHE_DIR=${PWD}/_ccache
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- _ccache/
build-alpine-meson:
image: alpine:edge
stage: build
script:
- apk add --no-cache python3 gtk+3.0-dev vala meson ninja libwnck3-dev build-base git gtk-layer-shell-dev
- meson bld --prefix=/usr && cd bld
- ninja dist
artifacts:
paths:
- "bld/meson-dist/vala-panel*.tar.xz"
expire_in: 1 week
release-main:
image: alpine:edge
stage: release
script:
- apk add --no-cache python3 py3-pip
- pip3 install gitlab_release
- python3 -m gitlab_release ${PRIVATE_TOKEN} bld/meson-dist/vala-panel*.tar.xz
only:
- tags
vala-panel-0.5.0/.gitlab-ci/ 0000775 0000000 0000000 00000000000 13736457142 0015461 5 ustar 00root root 0000000 0000000 vala-panel-0.5.0/.gitlab-ci/Dockerfile 0000664 0000000 0000000 00000000742 13736457142 0017456 0 ustar 00root root 0000000 0000000 FROM pritunl/archlinux
RUN pacman -S --noconfirm \
libwnck3 \
gtk3 \
vala \
cmake \
git \
base-devel \
clang \
ninja \
xfce4-panel \
mate-panel \
budgie-desktop \
gobject-introspection
ARG HOST_USER_ID=5555
ENV HOST_USER_ID ${HOST_USER_ID}
RUN useradd -u $HOST_USER_ID -ms /bin/bash user
USER user
WORKDIR /home/user
ENV LANG C.utf8
vala-panel-0.5.0/.gitlab/ 0000775 0000000 0000000 00000000000 13736457142 0015070 5 ustar 00root root 0000000 0000000 vala-panel-0.5.0/.gitlab/issue_templates/ 0000775 0000000 0000000 00000000000 13736457142 0020276 5 ustar 00root root 0000000 0000000 vala-panel-0.5.0/.gitlab/issue_templates/Bug.md 0000664 0000000 0000000 00000001316 13736457142 0021336 0 ustar 00root root 0000000 0000000 ### Prerequisites
* [ ] Are you running the latest version?
* [ ] Did you check the GDB debugging guide?
* [ ] Are you reporting to the correct repository?
* [ ] If it is a global menu issue, report to [vala-panel-appmenu](https://gitlab.com/vala-panel-project/vala-panel-appmenu)
### Description
[Description of the bug]
### Steps to Reproduce
1. [First Step]
2. [Second Step]
3. [and so on...]
**Expected behavior:** [What you expected to happen]
**Actual behavior:** [What actually happened]
#### Package version
You can get this information from executing `vala-panel --version`.
#### Linux Distribution
#### Link to downstream report of your Distribution
#### Screenshots or another examples
vala-panel-0.5.0/.gitlab/issue_templates/Crash.md 0000664 0000000 0000000 00000001514 13736457142 0021661 0 ustar 00root root 0000000 0000000 ### Prerequisites
* [ ] Are you running the latest version?
* [ ] Did you check the GDB debugging guide?
* [ ] Are you reporting to the correct repository?
* [ ] If it is a global menu issue, report to [vala-panel-appmenu](https://gitlab.com/vala-panel-project/vala-panel-appmenu)
### Description
[Description of the bug]
### Steps to Reproduce
1. [First Step]
2. [Second Step]
3. [and so on...]
#### Console log
*You can get this by running `vala-panel` in any terminal emulator*
*and then reproduce a crash*
#### GDB backtrace
*You can get this by running `gdb vala-panel` in any terminal emulator,*
*then reproduce a crash, and then run `bt` in gdb console*
#### Package version
You can get this information from executing `vala-panel --version`.
#### Linux Distribution
#### Link to downstream report of your Distribution
vala-panel-0.5.0/.gitlab/issue_templates/Request.md 0000664 0000000 0000000 00000001722 13736457142 0022252 0 ustar 00root root 0000000 0000000 ### Prerequisites
* [ ] Are you reporting to the correct repository?
* [ ] If it is a global menu request, report to [vala-panel-appmenu](https://gitlab.com/vala-panel-project/vala-panel-appmenu)
* [ ] If it is a request for a new module in [vala-panel-project](https://gitlab.com/vala-panel-project), please, set this checked
# Description
Please include a summary of the change and which feature you want.
Please also include relevant motivation and context.
List also a drawbacks of this feature.
## Type of change
Please delete options that are not relevant.
- [ ] Packaging request (request for build package or tarball)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update
# Benefits
Which benefits it will gives for me and for all [vala-panel-project](https://gitlab.com/vala-panel-project) vala-panel-0.5.0/.gitlab/merge_request_templates/ 0000775 0000000 0000000 00000000000 13736457142 0022015 5 ustar 00root root 0000000 0000000 vala-panel-0.5.0/.gitlab/merge_request_templates/Feature.md 0000664 0000000 0000000 00000002612 13736457142 0023733 0 ustar 00root root 0000000 0000000 # Description
Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context.
List any dependencies that are required for this change.
Fixes # (issue)
## Type of change
Please delete options that are not relevant.
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update
# How Has This Been Tested?
Please describe the tests that you ran to verify your changes.
Provide instructions so we can reproduce.
Please also list any relevant details for your test configuration
- [ ] Test A
- [ ] Test B
**Test Configuration**:
* Distribution version:
* Package versions: (cmake, vala, glib, gtk3, libwnck)
* Toolchain: (gcc, clang, glibc, musl)
# Checklist:
- [ ] My code follows the style guidelines of this project
- [ ] I ran `make clangformat` after any C code change
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings to relevant language (it is ok if Vala code generate C warnings)
- [ ] I have added tests that prove that my feature works
- [ ] Any dependent changes have been merged and published in downstream modules
vala-panel-0.5.0/.gitlab/merge_request_templates/Fix.md 0000664 0000000 0000000 00000002600 13736457142 0023063 0 ustar 00root root 0000000 0000000 # Description
Please include a summary of the change and which issue is fixed.
List any dependencies that are required for this change.
Fixes # (issue)
## Type of change
Please delete options that are not relevant.
- [ ] Simple fix (like an one-like typo fix)
- [ ] Workaround (any change than will workaround a bug in upstream libraries)
- [ ] Breaking change (fix that would cause existing functionality to not work as expected)
- [ ] Documentation or translation update
# How Has This Been Tested?
Please describe the tests that you ran to verify your changes.
Provide instructions so we can reproduce.
Please also list any relevant details for your test configuration
- [ ] Test A
- [ ] Test B
**Test Configuration**:
* Distribution version:
* Package versions: (cmake, vala, glib, gtk3, libwnck)
* Toolchain: (gcc, clang, glibc, musl)
# Checklist:
- [ ] My code follows the style guidelines of this project
- [ ] I ran `make clangformat` after any C code change
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings to relevant language (it is ok if Vala code generate C warnings)
- [ ] I have added tests that prove my fix is effective
- [ ] Any dependent changes have been merged and published in downstream modules
vala-panel-0.5.0/LICENSE 0000664 0000000 0000000 00000016417 13736457142 0014566 0 ustar 00root root 0000000 0000000
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright © 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, “this License” refers to version 3 of the GNU Lesser General Public License, and the “GNU GPL” refers to version 3 of the GNU General Public License.
“The Library” refers to a covered work governed by this License, other than an Application or a Combined Work as defined below.
An “Application” is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library.
A “Combined Work” is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the “Linked Version”.
The “Minimal Corresponding Source” for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version.
The “Corresponding Application Code” for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version:
a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following:
a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license document.
c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.
1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version.
e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library.
vala-panel-0.5.0/README.md 0000664 0000000 0000000 00000004332 13736457142 0015031 0 ustar 00root root 0000000 0000000 Vala Panel
===
This is Vala rewrite of [SimplePanel](https://github.com/rilian-la-te/simple-panel), GTK3 LXPanel fork.
TODO
---
* [x] Rewrite core panel in Vala (0.2)
* [x] Rewrite builtin plugins in Vala using libpeas. (0.2)
* [x] Write Vala Panel Plugin wrapper for LXTray from simple-panel (it is less buggy) (0.2) (done in XEmbed plugin)
* [x] Make global menus from Unity Appindicator (rewrite it on Vala but without Ubuntu deps) (0.3) (see https://gitlab.com/vala-panel-project/vala-panel-appmenu)
* [x] Write a window buttons applet (0.3)
* [x] Going to C again (0.4.X)
* [ ] Write Notification Center Applet (0.6)
* [ ] Wayland support, make compositor and complete Wayland support(1.0)
* [ ] Taskbar DBus library for compositor (1.0)
* [x] ~~Redo ValaPanelIconGrid using GtkFlowBox and such wonders.~~ (not needed since I am already using FlowBox everywhere)
*TODO for 0.5.0*
* [x] Drop libpeas in favor to applets-new (use GIO Extensions to implement).
* [x] Implement free applet actions (not only menu)
* [x] Made pack-type useful
*TODO for 0.6.0*
* [ ] Be prepared for GTK4
* [ ] Replace XEmbed to proxy and move it to extras
* [ ] Remove all Solus code, rewrite IconTasks
* [ ] Implement Layer Shell Wayland backend
*Some notes about realization*
Plugin-based panel. Users/developers can provide their own custom applets,
which are fully integrated. They can be moved, added, removed again, and
even broken.
Dependencies:
---
*Core:*
* GLib (>= 2.56.0)
* GTK3 (>= 3.22.0)
*Plugins:*
* libwnck (>= 3.4.7)
* libX11
* valac
Lastly, always set `-DCMAKE_INSTALL_PREXIX=/usr` when using cmake. Otherwise you
won't be able to start the panel on most distros.
Author
---
* Athor
Special thanks
---
* [Ikey Doherty](mailto:ikey@evolve-os.com) for icontasklist.
* [XFCE Team](http://www.xfce.org/) for XFCE Tasklist.
* [LXPanel team](https://git.lxde.org/gitweb/?p=lxde/lxpanel.git;a=summary) for creating a base for my fork. Vala Panel uses LXPanel's tray code and other inspirations (generic-config-dialog for applets and lxpanel-like remote command system).
Inspirations
---
* [Budgie Desktop](https://github.com/budgie-desktop/budgie-desktop)
* [LXPanel](https://wiki.lxde.org/en/LXPanel)
vala-panel-0.5.0/app/ 0000775 0000000 0000000 00000000000 13736457142 0014330 5 ustar 00root root 0000000 0000000 vala-panel-0.5.0/app/app-about.ui 0000664 0000000 0000000 00000004476 13736457142 0016572 0 ustar 00root root 0000000 0000000
vala-panel-0.5.0/app/app-pref.ui 0000664 0000000 0000000 00000024773 13736457142 0016416 0 ustar 00root root 0000000 0000000
True
False
Application preferences
False
450
dialog
center
True
False
vertical
False
False
False
0
True
False
vertical
True
False
0
none
True
False
vertical
True
True
●
system-lock-screen
False
False
Lock screen command...
False
True
0
True
True
●
system-log-out
False
False
Logout manager...
False
True
1
True
True
●
system-shutdown
False
False
Shutdown application...
False
True
2
True
False
Preferred Applications:
False
True
0
True
False
0
none
True
False
vertical
Use dark theme
True
True
True
False
app.is-dark
0
True
False
True
0
True
False
Use custom CSS
True
True
True
False
app.is-custom
0
True
False
True
0
True
False
Select a CSS File
False
True
end
1
False
True
2
True
False
Widget Style
False
True
1
False
True
1
vala-panel-0.5.0/app/application.c 0000664 0000000 0000000 00000066056 13736457142 0017014 0 ustar 00root root 0000000 0000000 /*
* vala-panel
* Copyright (C) 2015-2017 Konstantin Pugin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#include "config.h"
#include "version.h"
#include "application.h"
#include "panel-layout.h"
#include "server.h"
#include "vala-panel-platform-standalone-layer-shell.h"
#include "vala-panel-platform-standalone-x11.h"
#ifdef GDK_WINDOWING_X11
#include
#endif
#ifdef GDK_WINDOWING_WAYLAND
#include
#endif
#include
#include
#include
#define PROFILE_TR N_("Use specified profile")
#define COMMAND_DES_TR N_("Run command on already opened panel")
#define REMOTE_DES_TR N_("Run remote command on panel applet")
#define DEFAULT_PROFILE "default"
#define VP_KEY_LOCK "lock-command"
#define VP_KEY_RUN "run-command"
#define VP_KEY_LOGOUT "logout-command"
#define VP_KEY_SHUTDOWN "shutdown-command"
#define VP_KEY_TERMINAL "terminal-command"
#define VP_KEY_DARK "is-dark"
#define VP_KEY_CUSTOM "is-custom"
#define VP_KEY_CSS "css"
struct _ValaPanelApplication
{
GtkApplication parent;
bool restart;
bool dark;
bool custom;
GSettings *config;
char *css;
ValaPanelPlatform *platform;
GtkCssProvider *provider;
char *profile;
char *lock_command;
char *run_command;
char *terminal_command;
char *logout_command;
char *shutdown_command;
};
G_DEFINE_TYPE(ValaPanelApplication, vala_panel_application, GTK_TYPE_APPLICATION)
static void activate_menu(GSimpleAction *simple, GVariant *param, gpointer data);
static void activate_panel_preferences(GSimpleAction *simple, GVariant *param, gpointer data);
static void activate_preferences(GSimpleAction *simple, GVariant *param, gpointer data);
static void activate_about(GSimpleAction *simple, GVariant *param, gpointer data);
static void activate_run(GSimpleAction *simple, GVariant *param, gpointer data);
static void activate_lock(GSimpleAction *simple, GVariant *param, gpointer data);
static void activate_logout(GSimpleAction *simple, GVariant *param, gpointer data);
static void activate_shutdown(GSimpleAction *simple, GVariant *param, gpointer data);
static void activate_exit(GSimpleAction *simple, GVariant *param, gpointer data);
static void activate_restart(GSimpleAction *simple, GVariant *param, gpointer data);
static const GOptionEntry entries[] = {
{ "version", 'v', 0, G_OPTION_ARG_NONE, NULL, N_("Print version and exit"), NULL },
{ "profile",
'p',
0,
G_OPTION_ARG_STRING,
NULL,
PROFILE_TR,
N_("Profile is a config file name. Default is \"default\"") },
{ "command",
'c',
0,
G_OPTION_ARG_STRING,
NULL,
COMMAND_DES_TR,
N_("A command for main vala-panel executable.") },
{ "remote-command",
'r',
0,
G_OPTION_ARG_STRING_ARRAY,
NULL,
REMOTE_DES_TR,
N_("A command for a plugin.") },
{ NULL }
};
static const GActionEntry vala_panel_application_app_entries[10] = {
{ "preferences", activate_preferences, NULL, NULL, NULL, { 0 } },
{ "panel-preferences", activate_panel_preferences, "s", NULL, NULL, { 0 } },
{ "about", activate_about, NULL, NULL, NULL, { 0 } },
{ "menu", activate_menu, NULL, NULL, NULL, { 0 } },
{ "run", activate_run, NULL, NULL, NULL, { 0 } },
{ "lock", activate_lock, NULL, NULL, NULL, { 0 } },
{ "logout", activate_logout, NULL, NULL, NULL, { 0 } },
{ "shutdown", activate_shutdown, NULL, NULL, NULL, { 0 } },
{ "quit", activate_exit, NULL, NULL, NULL, { 0 } },
{ "restart", activate_restart, NULL, NULL, NULL, { 0 } },
};
static const GActionEntry vala_panel_application_menu_entries[3] = {
{ "launch-id", activate_menu_launch_id, "s", NULL, NULL, { 0 } },
{ "launch-uri", activate_menu_launch_uri, "s", NULL, NULL, { 0 } },
{ "launch-command", activate_menu_launch_command, "s", NULL, NULL, { 0 } }
};
enum
{
APP_DUMMY_PROPERTY,
APP_PROFILE,
APP_RUN_COMMAND,
APP_TERMINAL_COMMAND,
APP_LOCK_COMMAND,
APP_LOGOUT_COMMAND,
APP_SHUTDOWN_COMMAND,
APP_IS_DARK,
APP_IS_CUSTOM,
APP_CSS,
APP_ALL
};
static GParamSpec *app_specs[APP_ALL];
static inline void destroy0(GtkWidget *x, G_GNUC_UNUSED void *data)
{
gtk_widget_destroy0(x);
}
static void apply_styling(ValaPanelApplication *app)
{
if (gtk_settings_get_default() != NULL)
g_object_set(gtk_settings_get_default(),
"gtk-application-prefer-dark-theme",
app->dark,
NULL);
if (app->custom)
{
if (app->provider)
{
gtk_style_context_remove_provider_for_screen(gdk_screen_get_default(),
GTK_STYLE_PROVIDER(
app->provider));
g_clear_object(&app->provider);
}
app->provider = css_apply_from_file_to_app_with_provider_and_priority(
app->css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
else if (app->provider)
{
gtk_style_context_remove_provider_for_screen(gdk_screen_get_default(),
GTK_STYLE_PROVIDER(app->provider));
g_clear_object(&app->provider);
}
}
ValaPanelApplication *vala_panel_application_new(void)
{
return (ValaPanelApplication *)g_object_new(vala_panel_application_get_type(),
"application-id",
"org.valapanel.application",
"flags",
G_APPLICATION_HANDLES_COMMAND_LINE,
"resource-base-path",
"/org/vala-panel/app",
NULL);
}
static void vala_panel_application_init(ValaPanelApplication *self)
{
self->restart = false;
self->profile = g_strdup(DEFAULT_PROFILE);
self->provider = NULL;
g_application_add_main_option_entries(G_APPLICATION(self), entries);
}
static void vala_panel_application_startup(GApplication *base)
{
ValaPanelApplication *self = (ValaPanelApplication *)base;
G_APPLICATION_CLASS(vala_panel_application_parent_class)->startup(base);
g_application_mark_busy((GApplication *)self);
setlocale(LC_CTYPE, "");
bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR);
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
textdomain(GETTEXT_PACKAGE);
gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), DATADIR "/images");
g_action_map_add_action_entries((GActionMap *)self,
vala_panel_application_app_entries,
G_N_ELEMENTS(vala_panel_application_app_entries),
self);
g_action_map_add_action_entries((GActionMap *)self,
vala_panel_application_menu_entries,
G_N_ELEMENTS(vala_panel_application_menu_entries),
self);
}
static void vala_panel_application_shutdown(GApplication *base)
{
g_autoptr(GSList) list = NULL;
GList *lst = gtk_application_get_windows(GTK_APPLICATION(base));
for (GList *il = lst; il != NULL; il = il->next)
list = g_slist_append(list, il->data);
for (GSList *il = list; il != NULL; il = il->next)
{
GtkWindow *w = GTK_WINDOW(il->data);
gtk_window_set_application(w, NULL);
}
G_APPLICATION_CLASS(vala_panel_application_parent_class)->shutdown(base);
if (VALA_PANEL_APPLICATION(base)->restart)
{
g_autoptr(GError) err = NULL;
char cwd[PATH_MAX];
char *cwdp = getcwd(cwd, PATH_MAX);
const char *argv[] = {
GETTEXT_PACKAGE, "-p", VALA_PANEL_APPLICATION(base)->profile, NULL
};
g_auto(GStrv) envp = g_get_environ();
g_spawn_async(cwdp,
(GStrv)argv,
envp,
G_SPAWN_SEARCH_PATH,
child_spawn_func,
NULL,
NULL,
&err);
if (err)
g_critical("%s\n", err->message);
}
}
static gint vala_panel_app_handle_local_options(G_GNUC_UNUSED GApplication *application,
GVariantDict *options)
{
if (g_variant_dict_contains(options, "version"))
{
g_print(_("%s - Version %s\n"), g_get_application_name(), VERSION);
return 0;
}
return -1;
}
static int vala_panel_app_command_line(GApplication *application,
GApplicationCommandLine *commandline)
{
g_autofree char *profile_name = NULL;
g_autofree char *ccommand = NULL;
g_auto(GStrv) cremote = NULL;
GVariantDict *options = g_application_command_line_get_options_dict(commandline);
if (g_variant_dict_lookup(options, "profile", "s", &profile_name))
g_object_set(G_OBJECT(application), "profile", profile_name, NULL);
if (g_variant_dict_lookup(options, "command", "s", &ccommand))
{
g_autofree char *name = NULL;
g_autoptr(GVariant) param = NULL;
g_autoptr(GError) err = NULL;
g_action_parse_detailed_name(ccommand, &name, ¶m, &err);
if (err)
g_warning("%s\n", err->message);
else if (g_action_map_lookup_action(G_ACTION_MAP(application), name))
g_action_group_activate_action(G_ACTION_GROUP(application), name, param);
else
{
g_auto(GStrv) listv =
g_action_group_list_actions(G_ACTION_GROUP(application));
g_autofree char *list = g_strjoinv(" ", listv);
g_application_command_line_printerr(
commandline,
_("%s: invalid command - %s. Doing nothing.\nValid commands: %s\n"),
g_get_application_name(),
ccommand,
list);
}
}
if (g_variant_dict_lookup(options, "remote-command", "as", &cremote))
{
if (g_strv_length(cremote) != 2)
{
g_autofree char *list = g_strjoinv(" ", cremote);
g_application_command_line_printerr(
commandline,
_("%s: invalid remote command - %s. Remote commands should have "
"exactly 2 arguments\n"),
g_get_application_name(),
list);
}
char *uuid = cremote[0];
char *command_name = cremote[1];
GtkApplication *app = GTK_APPLICATION(application);
GList *windows = gtk_application_get_windows(app);
for (GList *l = windows; l != NULL; l = l->next)
{
if (VALA_PANEL_IS_TOPLEVEL(l->data))
{
ValaPanelLayout *layout =
vala_panel_toplevel_get_layout(VALA_PANEL_TOPLEVEL(l->data));
GList *applets = vala_panel_layout_get_applets_list(layout);
for (GList *il = applets; il != NULL; il = il->next)
{
const char *gotten_uuid =
vala_panel_applet_get_uuid(VALA_PANEL_APPLET(il->data));
if (!g_strcmp0(uuid, gotten_uuid))
vala_panel_applet_remote_command(VALA_PANEL_APPLET(
il->data),
command_name);
}
g_list_free(applets);
}
}
}
g_application_activate(application);
return 0;
}
static bool load_settings(ValaPanelApplication *app)
{
g_autofree char *file = g_build_filename(PROFILES, app->profile, NULL);
g_autofree char *default_file = g_build_filename(PROFILES, DEFAULT_PROFILE, NULL);
bool loaded = false;
bool load_default = false;
if (g_file_test(file, G_FILE_TEST_EXISTS))
loaded = true;
if (!loaded && g_file_test(default_file, G_FILE_TEST_EXISTS))
{
loaded = true;
load_default = true;
}
g_autofree char *user_file = _user_config_file_name_new(app->profile);
if (!g_file_test(user_file, G_FILE_TEST_EXISTS) && loaded)
{
g_autoptr(GFile) src = g_file_new_for_path(load_default ? default_file : file);
g_autoptr(GFile) dest = g_file_new_for_path(user_file);
g_autoptr(GError) err = NULL;
g_file_copy(src, dest, G_FILE_COPY_BACKUP, NULL, NULL, NULL, &err);
if (err)
{
g_warning("Cannot init global config: %s\n", err->message);
return false;
}
}
#ifdef PLATFORM_LAYER_SHELL
if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default()))
app->platform = VALA_PANEL_PLATFORM(
vala_panel_platform_layer_new(GTK_APPLICATION(app), app->profile));
#endif
#ifdef PLATFORM_X11
if (GDK_IS_X11_DISPLAY(gdk_display_get_default()))
app->platform = VALA_PANEL_PLATFORM(
vala_panel_platform_x11_new(GTK_APPLICATION(app), app->profile));
#endif
ValaPanelCoreSettings *s = vala_panel_platform_get_settings(app->platform);
GSettingsBackend *config_backend = s->backend;
app->config = g_settings_new_with_backend_and_path(VALA_PANEL_BASE_SCHEMA,
config_backend,
VALA_PANEL_OBJECT_PATH);
vala_panel_bind_gsettings(app, app->config, VP_KEY_LOCK);
vala_panel_bind_gsettings(app, app->config, VP_KEY_RUN);
vala_panel_bind_gsettings(app, app->config, VP_KEY_LOGOUT);
vala_panel_bind_gsettings(app, app->config, VP_KEY_SHUTDOWN);
vala_panel_bind_gsettings(app, app->config, VP_KEY_TERMINAL);
vala_panel_bind_gsettings(app, app->config, VP_KEY_CSS);
vala_panel_add_gsettings_as_action(G_ACTION_MAP(app), app->config, VP_KEY_DARK);
vala_panel_add_gsettings_as_action(G_ACTION_MAP(app), app->config, VP_KEY_CUSTOM);
return true;
}
static void _ensure_user_config_dirs(void)
{
g_autofree char *dir = _user_config_file_name_new("");
/* make sure the private profile and panels dir exists */
g_mkdir_with_parents(dir, 0700);
}
void vala_panel_application_activate(GApplication *app)
{
static bool is_started = false;
ValaPanelApplication *self = VALA_PANEL_APPLICATION(app);
if (!is_started)
{
g_application_mark_busy(app);
/*load config*/
_ensure_user_config_dirs();
load_settings(self);
gdk_window_set_events(gdk_get_default_root_window(),
(GdkEventMask)(GDK_STRUCTURE_MASK | GDK_SUBSTRUCTURE_MASK |
GDK_PROPERTY_CHANGE_MASK));
if (G_UNLIKELY(!vala_panel_platform_start_panels_from_profile(VALA_PANEL_PLATFORM(
self->platform),
GTK_APPLICATION(app),
self->profile)))
{
g_warning("Config files / toplevels are not found.\n");
g_application_unmark_busy(app);
g_application_quit(app);
}
else
{
is_started = true;
apply_styling(VALA_PANEL_APPLICATION(app));
g_application_unmark_busy(app);
}
}
}
static void vala_panel_app_finalize(GObject *object)
{
ValaPanelApplication *app = VALA_PANEL_APPLICATION(object);
g_clear_object(&app->config);
g_clear_object(&app->platform);
g_free0(app->css);
g_free0(app->terminal_command);
g_free0(app->lock_command);
g_free0(app->run_command);
g_free0(app->logout_command);
g_free0(app->shutdown_command);
g_clear_object(&app->provider);
g_free0(app->profile);
G_OBJECT_CLASS(vala_panel_application_parent_class)->finalize(object);
}
static void vala_panel_app_set_property(GObject *object, uint id, const GValue *value,
GParamSpec *pspec)
{
ValaPanelApplication *app;
g_return_if_fail(VALA_PANEL_IS_APPLICATION(object));
app = VALA_PANEL_APPLICATION(object);
switch (id)
{
case APP_IS_DARK:
app->dark = g_value_get_boolean(value);
apply_styling(app);
g_object_notify_by_pspec(object, pspec);
break;
case APP_IS_CUSTOM:
app->custom = g_value_get_boolean(value);
apply_styling(app);
g_object_notify_by_pspec(object, pspec);
break;
case APP_TERMINAL_COMMAND:
g_free0(app->terminal_command);
app->terminal_command = g_strdup(g_value_get_string(value));
g_object_notify_by_pspec(object, pspec);
break;
case APP_RUN_COMMAND:
g_free0(app->run_command);
app->run_command = g_strdup(g_value_get_string(value));
g_object_notify_by_pspec(object, pspec);
break;
case APP_LOCK_COMMAND:
g_free0(app->lock_command);
app->lock_command = g_strdup(g_value_get_string(value));
g_object_notify_by_pspec(object, pspec);
break;
case APP_LOGOUT_COMMAND:
g_free0(app->logout_command);
app->logout_command = g_strdup(g_value_get_string(value));
g_object_notify_by_pspec(object, pspec);
break;
case APP_SHUTDOWN_COMMAND:
g_free0(app->shutdown_command);
app->shutdown_command = g_strdup(g_value_get_string(value));
g_object_notify_by_pspec(object, pspec);
break;
case APP_PROFILE:
g_free0(app->profile);
app->profile = g_strdup(g_value_get_string(value));
g_object_notify_by_pspec(object, pspec);
break;
case APP_CSS:
g_free0(app->css);
app->css = g_strdup(g_value_get_string(value));
apply_styling(app);
g_object_notify_by_pspec(object, pspec);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, id, pspec);
break;
}
}
static void vala_panel_app_get_property(GObject *object, uint id, GValue *value, GParamSpec *pspec)
{
ValaPanelApplication *app;
g_return_if_fail(VALA_PANEL_IS_APPLICATION(object));
app = VALA_PANEL_APPLICATION(object);
switch (id)
{
case APP_IS_DARK:
g_value_set_boolean(value, app->dark);
break;
case APP_IS_CUSTOM:
g_value_set_boolean(value, app->custom);
break;
case APP_RUN_COMMAND:
g_value_set_string(value, app->run_command);
break;
case APP_TERMINAL_COMMAND:
g_value_set_string(value, app->terminal_command);
break;
case APP_LOCK_COMMAND:
g_value_set_string(value, app->lock_command);
break;
case APP_LOGOUT_COMMAND:
g_value_set_string(value, app->logout_command);
break;
case APP_SHUTDOWN_COMMAND:
g_value_set_string(value, app->shutdown_command);
break;
case APP_PROFILE:
g_value_set_string(value, app->profile);
break;
case APP_CSS:
g_value_set_string(value, app->css);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, id, pspec);
break;
}
}
static inline void file_chooser_helper(GtkFileChooser *self, ValaPanelApplication *app)
{
g_autofree char *file = gtk_file_chooser_get_filename(self);
g_object_set(app, VP_KEY_CSS, file, NULL);
}
/* TODO: Move activate_menu to hidden toplevel interface, it is not X11-specific */
static void activate_menu(G_GNUC_UNUSED GSimpleAction *simple, G_GNUC_UNUSED GVariant *param,
gpointer data)
{
GtkApplication *app = GTK_APPLICATION(data);
GList *windows = gtk_application_get_windows(app);
for (GList *l = windows; l != NULL; l = l->next)
{
if (VALA_PANEL_IS_TOPLEVEL(l->data))
{
ValaPanelLayout *layout =
vala_panel_toplevel_get_layout(VALA_PANEL_TOPLEVEL(l->data));
GList *applets = vala_panel_layout_get_applets_list(layout);
for (GList *il = applets; il != NULL; il = il->next)
{
ValaPanelApplet *applet = VALA_PANEL_APPLET(il->data);
bool success = vala_panel_applet_remote_command(applet, "menu");
if (success)
break;
}
g_list_free(applets);
}
}
}
static void activate_panel_preferences(G_GNUC_UNUSED GSimpleAction *simple,
G_GNUC_UNUSED GVariant *param, gpointer data)
{
GtkApplication *app = GTK_APPLICATION(data);
GList *windows = gtk_application_get_windows(app);
g_autofree char *name = NULL;
for (GList *l = windows; l != NULL; l = l->next)
{
if (VALA_PANEL_IS_TOPLEVEL(l->data))
{
g_object_get(l->data, VP_KEY_UUID, &name, NULL);
if (!g_strcmp0(name, g_variant_get_string(param, NULL)))
{
vala_panel_toplevel_configure(l->data, "position");
break;
}
g_warning(_("No panel with this name found.\n"));
}
}
}
static void activate_preferences(G_GNUC_UNUSED GSimpleAction *simple, G_GNUC_UNUSED GVariant *param,
gpointer data)
{
static GtkDialog *pref_dialog = NULL;
ValaPanelApplication *self = VALA_PANEL_APPLICATION(data);
if (pref_dialog != NULL && GTK_IS_DIALOG(pref_dialog))
{
gtk_window_present(GTK_WINDOW(pref_dialog));
return;
}
g_autoptr(GtkBuilder) builder =
gtk_builder_new_from_resource("/org/vala-panel/app/pref.ui");
pref_dialog = GTK_DIALOG(gtk_builder_get_object(builder, "app-pref"));
gtk_application_add_window(GTK_APPLICATION(self), GTK_WINDOW(pref_dialog));
GObject *w = gtk_builder_get_object(builder, "logout");
g_settings_bind(self->config, VP_KEY_LOGOUT, w, "text", G_SETTINGS_BIND_DEFAULT);
w = gtk_builder_get_object(builder, "lock");
g_settings_bind(self->config, VP_KEY_LOCK, w, "text", G_SETTINGS_BIND_DEFAULT);
w = gtk_builder_get_object(builder, "shutdown");
g_settings_bind(self->config, VP_KEY_SHUTDOWN, w, "text", G_SETTINGS_BIND_DEFAULT);
w = gtk_builder_get_object(builder, "css-chooser");
g_settings_bind(self->config, VP_KEY_CUSTOM, w, "sensitive", G_SETTINGS_BIND_DEFAULT);
GtkFileChooserButton *f = GTK_FILE_CHOOSER_BUTTON(w);
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(f), self->css);
g_signal_connect(f, "file-set", G_CALLBACK(file_chooser_helper), self);
gtk_window_present(GTK_WINDOW(pref_dialog));
g_signal_connect(pref_dialog, "hide", G_CALLBACK(destroy0), &pref_dialog);
g_signal_connect_after(pref_dialog, "response", G_CALLBACK(destroy0), &pref_dialog);
}
static void activate_about(G_GNUC_UNUSED GSimpleAction *simple, G_GNUC_UNUSED GVariant *param,
G_GNUC_UNUSED gpointer data)
{
g_autoptr(GtkBuilder) builder =
gtk_builder_new_from_resource("/org/vala-panel/app/about.ui");
GtkAboutDialog *d = GTK_ABOUT_DIALOG(gtk_builder_get_object(builder, "valapanel-about"));
gtk_about_dialog_set_version(d, VERSION);
gtk_window_set_position(GTK_WINDOW(d), GTK_WIN_POS_CENTER);
gtk_window_present(GTK_WINDOW(d));
g_signal_connect(d, "destroy", G_CALLBACK(gtk_widget_destroy), NULL);
g_signal_connect(d, "response", G_CALLBACK(gtk_widget_destroy), NULL);
g_signal_connect(d, "hide", G_CALLBACK(gtk_widget_destroy), NULL);
}
static void activate_run(G_GNUC_UNUSED GSimpleAction *simple, G_GNUC_UNUSED GVariant *param,
gpointer data)
{
ValaPanelApplication *app = VALA_PANEL_APPLICATION(data);
g_autoptr(GVariant) par = g_variant_new_string(app->run_command);
activate_menu_launch_command(NULL, par, app);
}
static void activate_lock(G_GNUC_UNUSED GSimpleAction *simple, G_GNUC_UNUSED GVariant *param,
gpointer data)
{
ValaPanelApplication *app = VALA_PANEL_APPLICATION(data);
g_autoptr(GVariant) par = g_variant_new_string(app->lock_command);
activate_menu_launch_command(NULL, par, app);
}
static void activate_logout(G_GNUC_UNUSED GSimpleAction *simple, G_GNUC_UNUSED GVariant *param,
gpointer data)
{
ValaPanelApplication *app = VALA_PANEL_APPLICATION(data);
g_autoptr(GVariant) par = g_variant_new_string(app->logout_command);
activate_menu_launch_command(NULL, par, app);
}
static void activate_shutdown(G_GNUC_UNUSED GSimpleAction *simple, G_GNUC_UNUSED GVariant *param,
gpointer data)
{
ValaPanelApplication *app = VALA_PANEL_APPLICATION(data);
g_autoptr(GVariant) par = g_variant_new_string(app->shutdown_command);
activate_menu_launch_command(NULL, par, app);
}
static void activate_exit(G_GNUC_UNUSED GSimpleAction *simple, G_GNUC_UNUSED GVariant *param,
gpointer data)
{
ValaPanelApplication *app = VALA_PANEL_APPLICATION(data);
app->restart = false;
g_application_quit(G_APPLICATION(app));
}
static void activate_restart(G_GNUC_UNUSED GSimpleAction *simple, G_GNUC_UNUSED GVariant *param,
gpointer data)
{
ValaPanelApplication *app = VALA_PANEL_APPLICATION(data);
app->restart = true;
g_application_quit(G_APPLICATION(app));
}
static void vala_panel_application_class_init(ValaPanelApplicationClass *klass)
{
G_APPLICATION_CLASS(klass)->startup = vala_panel_application_startup;
G_APPLICATION_CLASS(klass)->shutdown = vala_panel_application_shutdown;
G_APPLICATION_CLASS(klass)->activate = vala_panel_application_activate;
G_APPLICATION_CLASS(klass)->handle_local_options = vala_panel_app_handle_local_options;
G_APPLICATION_CLASS(klass)->command_line = vala_panel_app_command_line;
G_OBJECT_CLASS(klass)->get_property = vala_panel_app_get_property;
G_OBJECT_CLASS(klass)->set_property = vala_panel_app_set_property;
G_OBJECT_CLASS(klass)->finalize = vala_panel_app_finalize;
app_specs[APP_PROFILE] = g_param_spec_string("profile",
"profile",
"profile",
"default",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
app_specs[APP_RUN_COMMAND] =
g_param_spec_string(VP_KEY_RUN,
VP_KEY_RUN,
VP_KEY_RUN,
NULL,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
app_specs[APP_TERMINAL_COMMAND] =
g_param_spec_string(VP_KEY_TERMINAL,
VP_KEY_TERMINAL,
VP_KEY_TERMINAL,
NULL,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
app_specs[APP_LOCK_COMMAND] =
g_param_spec_string(VP_KEY_LOCK,
VP_KEY_LOCK,
VP_KEY_LOCK,
NULL,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
app_specs[APP_LOGOUT_COMMAND] =
g_param_spec_string(VP_KEY_LOGOUT,
VP_KEY_LOGOUT,
VP_KEY_LOGOUT,
NULL,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
app_specs[APP_SHUTDOWN_COMMAND] =
g_param_spec_string(VP_KEY_SHUTDOWN,
VP_KEY_SHUTDOWN,
VP_KEY_SHUTDOWN,
NULL,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
app_specs[APP_IS_DARK] = g_param_spec_boolean(VP_KEY_DARK,
VP_KEY_DARK,
VP_KEY_DARK,
false,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
app_specs[APP_IS_CUSTOM] = g_param_spec_boolean(VP_KEY_CUSTOM,
VP_KEY_CUSTOM,
VP_KEY_CUSTOM,
false,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
app_specs[APP_CSS] = g_param_spec_string(VP_KEY_CSS,
VP_KEY_CSS,
VP_KEY_CSS,
NULL,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
g_object_class_install_properties(G_OBJECT_CLASS(klass), APP_ALL, app_specs);
}
int main(int argc, char *argv[])
{
ValaPanelApplication *app = vala_panel_application_new();
int ret = g_application_run(G_APPLICATION(app), argc, argv);
g_clear_object(&app);
return ret;
}
vala-panel-0.5.0/app/application.h 0000664 0000000 0000000 00000000433 13736457142 0017004 0 ustar 00root root 0000000 0000000 #ifndef APPLICATIONNEW_H
#define APPLICATIONNEW_H
#include
#include
G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE(ValaPanelApplication, vala_panel_application, VALA_PANEL, APPLICATION,
GtkApplication)
G_END_DECLS
#endif // APPLICATIONNEW_H
vala-panel-0.5.0/app/meson.build 0000664 0000000 0000000 00000001574 13736457142 0016501 0 ustar 00root root 0000000 0000000 app_sources = files(
'application.c',
'application.h'
)
platform_x11_sources = files(
'vala-panel-platform-standalone-x11.c',
'vala-panel-platform-standalone-x11.h'
)
platform_gtk_layer_sources = files(
'vala-panel-platform-standalone-layer-shell.c',
'vala-panel-platform-standalone-layer-shell.h'
)
app_res = gnome.compile_resources(
'app', 'vala-panel.gresource.xml',
source_dir: 'app',
c_name: 'app'
)
app_all_sources = app_sources
app_dependencies = [libvalapanel]
if(platforms['x11'])
app_all_sources += platform_x11_sources
endif
if(platforms['layer-shell'])
app_all_sources += platform_gtk_layer_sources
app_dependencies += gtk_layer_shell
endif
app = executable(
meson.project_name(),
app_all_sources, app_res, version,
dependencies: app_dependencies,
c_args: ['-DG_SETTINGS_ENABLE_BACKEND'],
install : true
)
vala-panel-0.5.0/app/vala-panel-platform-standalone-layer-shell.c 0000664 0000000 0000000 00000022571 13736457142 0024712 0 ustar 00root root 0000000 0000000 /*
* vala-panel
* Copyright (C) 2015-2017 Konstantin Pugin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#include
#include "config.h"
#include "definitions.h"
#include "gio/gsettingsbackend.h"
#include "server.h"
#include "vala-panel-platform-standalone-layer-shell.h"
#define VALA_PANEL_CONFIG_HEADER "global"
struct _ValaPanelPlatformLayer
{
ValaPanelPlatform __parent__;
GtkApplication *app;
char *profile;
};
#define g_key_file_load_from_config(f, p) \
g_key_file_load_from_file(f, \
_user_config_file_name(GETTEXT_PACKAGE, p, NULL), \
G_KEY_FILE_KEEP_COMMENTS, \
NULL)
G_DEFINE_TYPE(ValaPanelPlatformLayer, vala_panel_platform_layer, vala_panel_platform_get_type())
ValaPanelPlatformLayer *vala_panel_platform_layer_new(GtkApplication *app, const char *profile)
{
ValaPanelPlatformLayer *pl =
VALA_PANEL_PLATFORM_LAYER(g_object_new(vala_panel_platform_layer_get_type(), NULL));
pl->app = app;
pl->profile = g_strdup(profile);
g_autofree char *filename = _user_config_file_name_new(pl->profile);
g_autoptr(GSettingsBackend) backend =
g_keyfile_settings_backend_new(filename,
VALA_PANEL_OBJECT_PATH,
VALA_PANEL_CONFIG_HEADER);
vala_panel_platform_init_settings(VALA_PANEL_PLATFORM(pl), backend);
return pl;
}
static void predicate_func(const char *key, ValaPanelUnitSettings *value, ValaPanelPlatform *self)
{
bool is_toplevel = vala_panel_unit_settings_is_toplevel(value);
ValaPanelPlatformLayer *user_data = VALA_PANEL_PLATFORM_LAYER(self);
if (is_toplevel)
{
ValaPanelToplevel *unit = vala_panel_toplevel_new(user_data->app, self, key);
GtkWindow *win = GTK_WINDOW(unit);
vala_panel_platform_register_unit(self, win);
gtk_layer_init_for_window(win);
gtk_layer_set_layer(win, GTK_LAYER_SHELL_LAYER_TOP);
gtk_layer_set_namespace(win, "panel"); // FIXME: may have conflicts with mate-panel
vala_panel_toplevel_init_ui(unit);
gtk_application_add_window(user_data->app, win);
}
}
/*********************************************************************************************
* Positioning
*********************************************************************************************/
static void update_toplevel_geometry_for_all(GdkDisplay *scr, void *data)
{
GtkApplication *app = GTK_APPLICATION(data);
int mons = gdk_display_get_n_monitors(scr);
GList *win = gtk_application_get_windows(app);
for (GList *il = win; il != NULL; il = il->next)
{
if (VALA_PANEL_IS_TOPLEVEL(il->data))
{
ValaPanelToplevel *panel = (ValaPanelToplevel *)il->data;
vala_panel_update_visibility(panel, mons);
}
}
}
static void monitor_notify_cb(GObject *gobject, G_GNUC_UNUSED GParamSpec *pspec, gpointer user_data)
{
GdkMonitor *mon = GDK_MONITOR(gobject);
update_toplevel_geometry_for_all(gdk_monitor_get_display(mon), user_data);
}
static void monitors_update_init(void *user_data)
{
GdkDisplay *disp = gdk_display_get_default();
int mons = gdk_display_get_n_monitors(disp);
for (int i = 0; i < mons; i++)
{
GdkMonitor *mon = gdk_display_get_monitor(disp, i);
g_signal_connect(mon, "notify", G_CALLBACK(monitor_notify_cb), user_data);
}
}
static void monitors_update_finalize(void *user_data)
{
GdkDisplay *disp = gdk_display_get_default();
int mons = gdk_display_get_n_monitors(disp);
for (int i = 0; i < mons; i++)
{
GdkMonitor *mon = gdk_display_get_monitor(disp, i);
g_signal_handlers_disconnect_by_data(mon, user_data);
}
}
static void monitor_added_cb(GdkDisplay *scr, GdkMonitor *mon, void *data)
{
g_signal_connect(mon, "notify", G_CALLBACK(monitor_notify_cb), data);
update_toplevel_geometry_for_all(scr, data);
}
static void monitor_removed_cb(GdkDisplay *scr, GdkMonitor *mon, void *data)
{
g_signal_handlers_disconnect_by_data(mon, data);
update_toplevel_geometry_for_all(scr, data);
}
static const char *vpp_layer_get_name(ValaPanelPlatform *obj)
{
return "layer-shell";
}
static bool vpp_layer_start_panels_from_profile(ValaPanelPlatform *obj, GtkApplication *app,
G_GNUC_UNUSED const char *profile)
{
ValaPanelPlatformLayer *self = VALA_PANEL_PLATFORM_LAYER(obj);
ValaPanelCoreSettings *core = vala_panel_platform_get_settings(obj);
g_hash_table_foreach(core->all_units, (GHFunc)predicate_func, self);
monitors_update_init(app);
g_signal_connect(gdk_display_get_default(),
"monitor-added",
G_CALLBACK(monitor_added_cb),
self->app);
g_signal_connect(gdk_display_get_default(),
"monitor-removed",
G_CALLBACK(monitor_removed_cb),
self->app);
return vala_panel_platform_has_units_loaded(obj);
}
// TODO: Make more readable code without switch
static void vpp_layer_move_to_side(G_GNUC_UNUSED ValaPanelPlatform *f, GtkWindow *top,
PanelGravity gravity, int monitor)
{
bool anchor[GTK_LAYER_SHELL_EDGE_ENTRY_NUMBER] = { false };
switch (gravity)
{
case NORTH_LEFT:
case WEST_UP:
anchor[GTK_LAYER_SHELL_EDGE_LEFT] = true;
anchor[GTK_LAYER_SHELL_EDGE_TOP] = true;
break;
case NORTH_CENTER:
anchor[GTK_LAYER_SHELL_EDGE_TOP] = true;
break;
case EAST_UP:
case NORTH_RIGHT:
anchor[GTK_LAYER_SHELL_EDGE_RIGHT] = true;
anchor[GTK_LAYER_SHELL_EDGE_TOP] = true;
break;
case WEST_DOWN:
case SOUTH_LEFT:
anchor[GTK_LAYER_SHELL_EDGE_LEFT] = true;
anchor[GTK_LAYER_SHELL_EDGE_BOTTOM] = true;
break;
case SOUTH_CENTER:
anchor[GTK_LAYER_SHELL_EDGE_BOTTOM] = true;
break;
case EAST_DOWN:
case SOUTH_RIGHT:
anchor[GTK_LAYER_SHELL_EDGE_RIGHT] = true;
anchor[GTK_LAYER_SHELL_EDGE_BOTTOM] = true;
break;
case WEST_CENTER:
anchor[GTK_LAYER_SHELL_EDGE_LEFT] = true;
break;
case EAST_CENTER:
anchor[GTK_LAYER_SHELL_EDGE_RIGHT] = true;
break;
}
for (int i = 0; i < GTK_LAYER_SHELL_EDGE_ENTRY_NUMBER; i++)
gtk_layer_set_anchor(top, i, anchor[i]);
}
static bool vpp_layer_edge_can_strut(G_GNUC_UNUSED ValaPanelPlatform *f, GtkWindow *top)
{
int strut_set = false;
g_object_get(top, VP_KEY_STRUT, &strut_set, NULL);
if (!gtk_widget_get_mapped(GTK_WIDGET(top)))
return false;
return strut_set;
}
static void vpp_layer_update_strut(ValaPanelPlatform *f, GtkWindow *top)
{
if (vala_panel_platform_can_strut(f, top))
gtk_layer_auto_exclusive_zone_enable(top);
else
gtk_layer_set_exclusive_zone(top, 0);
}
static bool vpp_layer_edge_available(ValaPanelPlatform *self, GtkWindow *top, PanelGravity gravity,
int monitor)
{
ValaPanelPlatformLayer *pl = VALA_PANEL_PLATFORM_LAYER(self);
int edge = vala_panel_edge_from_gravity(gravity);
bool strut = true;
g_object_get(top, VP_KEY_STRUT, &strut, NULL);
if (!strut)
{
return strut;
}
for (g_autoptr(GList) w = gtk_application_get_windows(pl->app); w != NULL; w = w->next)
if (VALA_PANEL_IS_TOPLEVEL(w))
{
ValaPanelToplevel *pl = VALA_PANEL_TOPLEVEL(w->data);
bool have_toplevel = VALA_PANEL_IS_TOPLEVEL(top);
int smonitor = 0;
PanelGravity sgravity;
g_object_get(pl,
VP_KEY_MONITOR,
&smonitor,
VP_KEY_GRAVITY,
&sgravity,
NULL);
if ((!have_toplevel || (pl != VALA_PANEL_TOPLEVEL(top))) &&
(vala_panel_edge_from_gravity(sgravity) == edge) &&
((monitor == smonitor) || smonitor < 0))
return false;
}
return true;
}
static void vpp_layer_finalize(GObject *obj)
{
ValaPanelPlatformLayer *self = VALA_PANEL_PLATFORM_LAYER(obj);
g_signal_handlers_disconnect_by_data(gdk_display_get_default(), self->app);
monitors_update_finalize(self->app);
g_clear_pointer(&self->profile, g_free);
G_OBJECT_CLASS(vala_panel_platform_layer_parent_class)->finalize(obj);
}
static void vala_panel_platform_layer_init(G_GNUC_UNUSED ValaPanelPlatformLayer *self)
{
}
static void vala_panel_platform_layer_class_init(ValaPanelPlatformLayerClass *klass)
{
VALA_PANEL_PLATFORM_CLASS(klass)->get_name = vpp_layer_get_name;
VALA_PANEL_PLATFORM_CLASS(klass)->move_to_side = vpp_layer_move_to_side;
VALA_PANEL_PLATFORM_CLASS(klass)->update_strut = vpp_layer_update_strut;
VALA_PANEL_PLATFORM_CLASS(klass)->can_strut = vpp_layer_edge_can_strut;
VALA_PANEL_PLATFORM_CLASS(klass)->start_panels_from_profile =
vpp_layer_start_panels_from_profile;
VALA_PANEL_PLATFORM_CLASS(klass)->edge_available = vpp_layer_edge_available;
G_OBJECT_CLASS(klass)->finalize = vpp_layer_finalize;
}
vala-panel-0.5.0/app/vala-panel-platform-standalone-layer-shell.h 0000664 0000000 0000000 00000002552 13736457142 0024714 0 ustar 00root root 0000000 0000000 /*
* vala-panel
* Copyright (C) 2015-2017 Konstantin Pugin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#ifndef VALAPANELPLATFORMSTANDALONELAYER_H
#define VALAPANELPLATFORMSTANDALONELAYER_H
#include "panel-platform.h"
#include
G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE(ValaPanelPlatformLayer, vala_panel_platform_layer, VALA_PANEL, PLATFORM_LAYER,
ValaPanelPlatform)
ValaPanelPlatformLayer *vala_panel_platform_layer_new(GtkApplication *app, const char *profile);
#define _user_config_file_name_new(cprofile) \
g_build_filename(g_get_user_config_dir(), GETTEXT_PACKAGE, cprofile, NULL)
G_END_DECLS
#endif // VALAPANELPLATFORMSTANDALONELAYER_H
vala-panel-0.5.0/app/vala-panel-platform-standalone-x11.c 0000664 0000000 0000000 00000030444 13736457142 0023100 0 ustar 00root root 0000000 0000000 /*
* vala-panel
* Copyright (C) 2015-2017 Konstantin Pugin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#include "config.h"
#include "definitions.h"
#include "gio/gsettingsbackend.h"
#include "server.h"
#include "vala-panel-platform-standalone-x11.h"
#define VALA_PANEL_CONFIG_HEADER "global"
struct _ValaPanelPlatformX11
{
ValaPanelPlatform __parent__;
GtkApplication *app;
char *profile;
};
#define g_key_file_load_from_config(f, p) \
g_key_file_load_from_file(f, \
_user_config_file_name(GETTEXT_PACKAGE, p, NULL), \
G_KEY_FILE_KEEP_COMMENTS, \
NULL)
G_DEFINE_TYPE(ValaPanelPlatformX11, vala_panel_platform_x11, vala_panel_platform_get_type())
ValaPanelPlatformX11 *vala_panel_platform_x11_new(GtkApplication *app, const char *profile)
{
ValaPanelPlatformX11 *pl =
VALA_PANEL_PLATFORM_X11(g_object_new(vala_panel_platform_x11_get_type(), NULL));
pl->app = app;
pl->profile = g_strdup(profile);
g_autofree char *filename = _user_config_file_name_new(pl->profile);
g_autoptr(GSettingsBackend) backend =
g_keyfile_settings_backend_new(filename,
VALA_PANEL_OBJECT_PATH,
VALA_PANEL_CONFIG_HEADER);
vala_panel_platform_init_settings(VALA_PANEL_PLATFORM(pl), backend);
return pl;
}
static void predicate_func(const char *key, ValaPanelUnitSettings *value, ValaPanelPlatform *self)
{
bool is_toplevel = vala_panel_unit_settings_is_toplevel(value);
ValaPanelPlatformX11 *user_data = VALA_PANEL_PLATFORM_X11(self);
if (is_toplevel)
{
ValaPanelToplevel *unit = vala_panel_toplevel_new(user_data->app, self, key);
vala_panel_platform_register_unit(self, GTK_WINDOW(unit));
vala_panel_toplevel_init_ui(unit);
gtk_application_add_window(user_data->app, GTK_WINDOW(unit));
}
}
/*********************************************************************************************
* Positioning
*********************************************************************************************/
static void update_toplevel_geometry_for_all(GdkDisplay *scr, void *data)
{
GtkApplication *app = GTK_APPLICATION(data);
int mons = gdk_display_get_n_monitors(scr);
GList *win = gtk_application_get_windows(app);
for (GList *il = win; il != NULL; il = il->next)
{
if (VALA_PANEL_IS_TOPLEVEL(il->data))
{
ValaPanelToplevel *panel = (ValaPanelToplevel *)il->data;
vala_panel_update_visibility(panel, mons);
}
}
}
static void monitor_notify_cb(GObject *gobject, G_GNUC_UNUSED GParamSpec *pspec, gpointer user_data)
{
GdkMonitor *mon = GDK_MONITOR(gobject);
update_toplevel_geometry_for_all(gdk_monitor_get_display(mon), user_data);
}
static void monitors_update_init(void *user_data)
{
GdkDisplay *disp = gdk_display_get_default();
int mons = gdk_display_get_n_monitors(disp);
for (int i = 0; i < mons; i++)
{
GdkMonitor *mon = gdk_display_get_monitor(disp, i);
g_signal_connect(mon, "notify", G_CALLBACK(monitor_notify_cb), user_data);
}
}
static void monitors_update_finalize(void *user_data)
{
GdkDisplay *disp = gdk_display_get_default();
int mons = gdk_display_get_n_monitors(disp);
for (int i = 0; i < mons; i++)
{
GdkMonitor *mon = gdk_display_get_monitor(disp, i);
g_signal_handlers_disconnect_by_data(mon, user_data);
}
}
static void monitor_added_cb(GdkDisplay *scr, GdkMonitor *mon, void *data)
{
g_signal_connect(mon, "notify", G_CALLBACK(monitor_notify_cb), data);
update_toplevel_geometry_for_all(scr, data);
}
static void monitor_removed_cb(GdkDisplay *scr, GdkMonitor *mon, void *data)
{
g_signal_handlers_disconnect_by_data(mon, data);
update_toplevel_geometry_for_all(scr, data);
}
static const char *vpp_x11_get_name(ValaPanelPlatform *obj)
{
return "x11";
}
static bool vpp_x11_start_panels_from_profile(ValaPanelPlatform *obj, GtkApplication *app,
G_GNUC_UNUSED const char *profile)
{
ValaPanelPlatformX11 *self = VALA_PANEL_PLATFORM_X11(obj);
ValaPanelCoreSettings *core = vala_panel_platform_get_settings(obj);
g_hash_table_foreach(core->all_units, (GHFunc)predicate_func, self);
monitors_update_init(app);
g_signal_connect(gdk_display_get_default(),
"monitor-added",
G_CALLBACK(monitor_added_cb),
self->app);
g_signal_connect(gdk_display_get_default(),
"monitor-removed",
G_CALLBACK(monitor_removed_cb),
self->app);
return vala_panel_platform_has_units_loaded(obj);
}
// TODO: Make more readable code without switch
static void vpp_x11_move_to_side(G_GNUC_UNUSED ValaPanelPlatform *f, GtkWindow *top,
PanelGravity gravity, int monitor)
{
GtkOrientation orient = vala_panel_orient_from_gravity(gravity);
GdkMonitor *mon = vala_panel_platform_get_suitable_monitor(GTK_WIDGET(top), monitor);
GdkRectangle marea;
int x = 0, y = 0;
gdk_monitor_get_geometry(mon, &marea);
GtkRequisition size, min;
gtk_widget_get_preferred_size(GTK_WIDGET(top), &min, &size);
int height = orient == GTK_ORIENTATION_HORIZONTAL ? size.height : size.width;
int width = orient == GTK_ORIENTATION_HORIZONTAL ? size.width : size.height;
switch (gravity)
{
case NORTH_LEFT:
case WEST_UP:
x = marea.x;
y = marea.y;
break;
case NORTH_CENTER:
x = marea.x + (marea.width - width) / 2;
y = marea.y;
break;
case NORTH_RIGHT:
x = marea.x + marea.width - width;
y = marea.y;
break;
case SOUTH_LEFT:
x = marea.x;
y = marea.y + marea.height - height;
break;
case SOUTH_CENTER:
x = marea.x + (marea.width - width) / 2;
y = marea.y + marea.height - height;
break;
case SOUTH_RIGHT:
x = marea.x + marea.width - width;
y = marea.y + marea.height - height;
break;
case WEST_CENTER:
x = marea.x;
y = marea.y + (marea.height - width) / 2;
break;
case WEST_DOWN:
x = marea.x;
y = marea.y + (marea.height - width);
break;
case EAST_UP:
x = marea.x + marea.width - height;
y = marea.y;
break;
case EAST_CENTER:
x = marea.x + marea.width - height;
y = marea.y + (marea.height - width) / 2;
break;
case EAST_DOWN:
x = marea.x + marea.width - height;
y = marea.y + (marea.height - width);
break;
}
gtk_window_move(top, x, y);
}
static bool vpp_x11_edge_can_strut(G_GNUC_UNUSED ValaPanelPlatform *f, GtkWindow *top)
{
int strut_set = false;
g_object_get(top, VP_KEY_STRUT, &strut_set, NULL);
if (!gtk_widget_get_mapped(GTK_WIDGET(top)))
return false;
return strut_set;
}
static void vpp_x11_update_strut(ValaPanelPlatform *f, GtkWindow *top)
{
bool autohide;
PanelGravity gravity;
int monitor;
int size, len;
g_object_get(top,
VP_KEY_AUTOHIDE,
&autohide,
VP_KEY_GRAVITY,
&gravity,
VP_KEY_MONITOR,
&monitor,
VP_KEY_HEIGHT,
&size,
VP_KEY_WIDTH,
&len,
NULL);
GdkRectangle primary_monitor_rect;
GtkPositionType edge = vala_panel_edge_from_gravity(gravity);
long struts[12] = { 0 };
GdkMonitor *mon = vala_panel_platform_get_suitable_monitor(GTK_WIDGET(top), monitor);
int scale_factor = gdk_monitor_get_scale_factor(mon);
gdk_monitor_get_geometry(mon, &primary_monitor_rect);
/*
strut-left strut-right strut-top strut-bottom
strut-left-start-y strut-left-end-y
strut-right-start-y strut-right-end-y
strut-top-start-x strut-top-end-x
strut-bottom-start-x strut-bottom-end-x
*/
if (!gtk_widget_get_realized(GTK_WIDGET(top)))
return;
int panel_size = autohide ? GAP : size;
// Struts dependent on position
switch (edge)
{
case GTK_POS_TOP:
struts[2] = (primary_monitor_rect.y + panel_size) * scale_factor;
struts[8] = (primary_monitor_rect.x) * scale_factor;
struts[9] = (primary_monitor_rect.x + primary_monitor_rect.width / 100 * len) *
scale_factor;
break;
case GTK_POS_LEFT:
struts[0] = panel_size * scale_factor;
struts[4] = primary_monitor_rect.y * scale_factor;
struts[5] = (primary_monitor_rect.y + primary_monitor_rect.height / 100 * len) *
scale_factor;
break;
case GTK_POS_RIGHT:
struts[1] = panel_size * scale_factor;
struts[6] = primary_monitor_rect.y * scale_factor;
struts[7] = (primary_monitor_rect.y + primary_monitor_rect.height / 100 * len) *
scale_factor;
break;
case GTK_POS_BOTTOM:
struts[3] = (primary_monitor_rect.y + panel_size) * scale_factor;
struts[10] = primary_monitor_rect.x * scale_factor;
struts[11] = (primary_monitor_rect.x + primary_monitor_rect.width / 100 * len) *
scale_factor;
break;
}
GdkAtom atom = gdk_atom_intern_static_string("_NET_WM_STRUT_PARTIAL");
GdkAtom old_atom = gdk_atom_intern_static_string("_NET_WM_STRUT");
GdkWindow *xwin = gtk_widget_get_window(GTK_WIDGET(top));
if (vala_panel_platform_can_strut(f, top))
{
gdk_property_change(xwin,
atom,
gdk_atom_intern_static_string("CARDINAL"),
32,
GDK_PROP_MODE_REPLACE,
(unsigned char *)struts,
12);
gdk_property_change(xwin,
old_atom,
gdk_atom_intern_static_string("CARDINAL"),
32,
GDK_PROP_MODE_REPLACE,
(unsigned char *)struts,
4);
}
else
{
gdk_property_delete(xwin, atom);
gdk_property_delete(xwin, old_atom);
}
}
static bool vpp_x11_edge_available(ValaPanelPlatform *self, GtkWindow *top, PanelGravity gravity,
int monitor)
{
ValaPanelPlatformX11 *pl = VALA_PANEL_PLATFORM_X11(self);
int edge = vala_panel_edge_from_gravity(gravity);
bool strut = true;
g_object_get(top, VP_KEY_STRUT, &strut, NULL);
if (!strut)
{
return strut;
}
for (g_autoptr(GList) w = gtk_application_get_windows(pl->app); w != NULL; w = w->next)
if (VALA_PANEL_IS_TOPLEVEL(w))
{
ValaPanelToplevel *pl = VALA_PANEL_TOPLEVEL(w->data);
bool have_toplevel = VALA_PANEL_IS_TOPLEVEL(top);
int smonitor = 0;
PanelGravity sgravity;
g_object_get(pl,
VP_KEY_MONITOR,
&smonitor,
VP_KEY_GRAVITY,
&sgravity,
NULL);
if ((!have_toplevel || (pl != VALA_PANEL_TOPLEVEL(top))) &&
(vala_panel_edge_from_gravity(sgravity) == edge) &&
((monitor == smonitor) || smonitor < 0))
return false;
}
return true;
}
static void vpp_x11_finalize(GObject *obj)
{
ValaPanelPlatformX11 *self = VALA_PANEL_PLATFORM_X11(obj);
g_signal_handlers_disconnect_by_data(gdk_display_get_default(), self->app);
monitors_update_finalize(self->app);
g_clear_pointer(&self->profile, g_free);
G_OBJECT_CLASS(vala_panel_platform_x11_parent_class)->finalize(obj);
}
static void vala_panel_platform_x11_init(G_GNUC_UNUSED ValaPanelPlatformX11 *self)
{
}
static void vala_panel_platform_x11_class_init(ValaPanelPlatformX11Class *klass)
{
VALA_PANEL_PLATFORM_CLASS(klass)->get_name = vpp_x11_get_name;
VALA_PANEL_PLATFORM_CLASS(klass)->move_to_side = vpp_x11_move_to_side;
VALA_PANEL_PLATFORM_CLASS(klass)->update_strut = vpp_x11_update_strut;
VALA_PANEL_PLATFORM_CLASS(klass)->can_strut = vpp_x11_edge_can_strut;
VALA_PANEL_PLATFORM_CLASS(klass)->start_panels_from_profile =
vpp_x11_start_panels_from_profile;
VALA_PANEL_PLATFORM_CLASS(klass)->edge_available = vpp_x11_edge_available;
G_OBJECT_CLASS(klass)->finalize = vpp_x11_finalize;
}
vala-panel-0.5.0/app/vala-panel-platform-standalone-x11.h 0000664 0000000 0000000 00000002532 13736457142 0023102 0 ustar 00root root 0000000 0000000 /*
* vala-panel
* Copyright (C) 2015-2017 Konstantin Pugin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#ifndef VALAPANELPLATFORMSTANDALONEX11_H
#define VALAPANELPLATFORMSTANDALONEX11_H
#include "panel-platform.h"
#include
G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE(ValaPanelPlatformX11, vala_panel_platform_x11, VALA_PANEL, PLATFORM_X11,
ValaPanelPlatform)
ValaPanelPlatformX11 *vala_panel_platform_x11_new(GtkApplication *app, const char *profile);
#define _user_config_file_name_new(cprofile) \
g_build_filename(g_get_user_config_dir(), GETTEXT_PACKAGE, cprofile, NULL)
G_END_DECLS
#endif // VALAPANELPLATFORMSTANDALONEX11_H
vala-panel-0.5.0/app/vala-panel.gresource.xml 0000664 0000000 0000000 00000001042 13736457142 0021064 0 ustar 00root root 0000000 0000000
app-pref.ui
app-about.ui
../data/css/vala-panel.css
../data/images/panel.svg
../data/images/panel.png
vala-panel-0.5.0/applets/ 0000775 0000000 0000000 00000000000 13736457142 0015220 5 ustar 00root root 0000000 0000000 vala-panel-0.5.0/applets/core/ 0000775 0000000 0000000 00000000000 13736457142 0016150 5 ustar 00root root 0000000 0000000 vala-panel-0.5.0/applets/core/clock/ 0000775 0000000 0000000 00000000000 13736457142 0017243 5 ustar 00root root 0000000 0000000 vala-panel-0.5.0/applets/core/clock/clock.vala 0000664 0000000 0000000 00000024615 13736457142 0021213 0 ustar 00root root 0000000 0000000 /*
* vala-panel
* Copyright (C) 2015 Konstantin Pugin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
using ValaPanel;
using Gtk;
public class Clock: Applet
{
private const string TIP_FORMAT = "tooltip-format";
private const string LABEL_FORMAT = "clock-format";
private const string BOLD = "bold-font";
private ToggleButton clock;
private enum Interval
{
AWAITING_FIRST_CHANGE = 0, /* Experimenting to determine interval, waiting for first change */
AWAITING_SECOND_CHANGE = 1, /* Experimenting to determine interval, waiting for second change */
ONE_SECOND = 2, /* Determined that one second interval is necessary */
ONE_MINUTE = 3 /* Determined that one minute interval is sufficient */
}
private Interval exp_interval;
private int exp_count;
private string? prev_clock_val;
private uint timer;
private Window calendar;
internal string clock_format {get; set;}
internal string tooltip_format {get; set;}
internal bool bold_font {get; set;}
public Clock(ValaPanel.Toplevel toplevel,
GLib.Settings? settings,
string number)
{
base(toplevel,settings,number);
}
public override void constructed()
{
(this.action_group.lookup_action(AppletAction.CONFIGURE) as SimpleAction).set_enabled(true);
settings.bind(LABEL_FORMAT,this,LABEL_FORMAT,SettingsBindFlags.GET);
settings.bind(TIP_FORMAT,this,TIP_FORMAT,SettingsBindFlags.GET);
settings.bind(BOLD,this,BOLD,SettingsBindFlags.GET);
clock = new ToggleButton();
ValaPanel.setup_button(clock as Button,null,null);
clock.toggled.connect(()=>{
if (clock.get_active())
{
calendar = create_calendar();
calendar.show();
}
else
{
calendar.destroy();
calendar = null;
}
});
this.notify.connect((pspec)=>{
if (pspec.name == BOLD)
PanelCSS.apply_with_class(clock,get_css(),"-vala-panel-font-weight",false);
else
{
if (timer != 0) Source.remove(timer);
prev_clock_val = null;
exp_count = 0;
exp_interval = Interval.AWAITING_FIRST_CHANGE;
DateTime now = new DateTime.now_local();
timer_set(now);
if (calendar != null)
{
calendar.destroy();
calendar = null;
}
}
});
clock.show();
this.add(clock);
this.show();
}
public override Widget get_settings_ui()
{
return Configurator.generic_config_widget(this.settings,
_("Clock Format"), LABEL_FORMAT, GenericConfigType.STR,
_("Tooltip Format"), TIP_FORMAT, GenericConfigType.STR,
_("Format codes: man 3 strftime; %n for line break"), null, GenericConfigType.TRIM,
_("Bold font"), BOLD, GenericConfigType.BOOL);
}
private void popup_position_helper(Gtk.Widget popup,
out int x, out int y)
{
Gtk.Allocation pa;
Gtk.Allocation a;
popup.realize();
popup.get_allocation(out pa);
if (popup.is_toplevel())
{
Gdk.Rectangle ext;
popup.get_window().get_frame_extents(out ext);
pa.width = ext.width;
pa.height = ext.height;
}
if (popup is Gtk.Menu)
{
int min, nat, new_height = 0;
foreach (var item in (popup as Gtk.Menu).get_children())
{
item.get_preferred_height(out min, out nat);
new_height += nat;
}
pa.height = int.max(pa.height,new_height);
}
get_allocation(out a);
get_window().get_origin(out x, out y);
if (!get_has_window())
{
x += a.x;
y += a.y;
}
var edge = edge_from_gravity(toplevel.panel_gravity);
switch (edge)
{
case Gtk.PositionType.TOP:
y+=a.height;
break;
case Gtk.PositionType.BOTTOM:
y-=pa.height;
break;
case Gtk.PositionType.LEFT:
x+=a.width;
break;
case Gtk.PositionType.RIGHT:
x-=pa.width;
break;
}
unowned Gdk.Monitor monitor = get_display().get_monitor_at_point(x,y);
a = (Gtk.Allocation)monitor.get_workarea();
x = x.clamp(a.x,a.x + a.width - pa.width);
y = y.clamp(a.y,a.y + a.height - pa.height);
}
private void set_popup_position(Gtk.Widget popup)
{
int x,y;
popup_position_helper(popup,out x, out y);
if (popup is Gtk.Window)
(popup as Window).move(x,y);
else
popup.get_window().move(x,y);
}
private string get_css()
{
return ".-vala-panel-font-weight{\n"
+ " font-weight: %s;\n".printf(bold_font ? "bold" : "normal")
+ "}";
}
private Window create_calendar()
{
/* Create a new window. */
var win = new Window(WindowType.POPUP);
win.set_default_size(180, 180);
win.set_border_width(5);
/* Create a standard calendar widget as a child of the window. */
var calendar = new Calendar();
var now = new DateTime.now_local();
calendar.set_display_options(CalendarDisplayOptions.SHOW_WEEK_NUMBERS
| CalendarDisplayOptions.SHOW_DAY_NAMES
| CalendarDisplayOptions.SHOW_HEADING);
calendar.mark_day(now.get_day_of_month());
win.add(calendar);
/* Preset the widget position right now to not move it across the screen */
win.set_type_hint(Gdk.WindowTypeHint.UTILITY);
win.set_transient_for(this.toplevel);
win.set_attached_to(this.toplevel);
calendar.show();
set_popup_position(win);
/* Return the widget. */
return win;
}
/* Periodic timer callback.
* Also used during initialization and configuration change to do a redraw. */
private bool update_display()
{
/* Determine the current time. */
var now = new DateTime.now_local();
if (MainContext.current_source().is_destroyed())
return false;
timer_set(now);
/* Determine the content of the clock label and tooltip. */
string label = now.format(clock_format);
string tooltip = now.format(tooltip_format);
/* When we write the clock value, it causes the panel to do a full relayout.
* Since this function may be called too often while the timing experiment is underway,
* we take the trouble to check if the string actually changed first. */
clock.set_label(label);
clock.set_tooltip_text(tooltip);
/* Conduct an experiment to see how often the value changes.
* Use this to decide whether we update the value every second or every minute.
* We need to account for the possibility that the experiment is being run when we cross a minute boundary. */
if (exp_interval < Interval.ONE_SECOND)
{
if (prev_clock_val == null)
/* Initiate the experiment. */
prev_clock_val = label;
else
{
if (prev_clock_val == label)
{
exp_count += 1;
if (exp_count > 3)
{
/* No change within 3 seconds. Assume change no more often than once per minute. */
exp_interval = Interval.ONE_MINUTE;
prev_clock_val = null;
}
}
else if (exp_interval == Interval.AWAITING_FIRST_CHANGE)
{
/* We have a change at the beginning of the experiment, but we do not know when the next change might occur.
* Continue the experiment for 3 more seconds. */
exp_interval = Interval.AWAITING_SECOND_CHANGE;
exp_count = 0;
prev_clock_val = label;
}
else
{
/* We have a second change. End the experiment. */
exp_interval = ((exp_count > 3) ? Interval.ONE_MINUTE : Interval.ONE_SECOND);
prev_clock_val = null;
}
}
}
/* Reset the timer and return. */
return false;
}
/* Set the timer. */
private void timer_set(DateTime current_time)
{
uint microseconds = 1000000;
/* Compute number of microseconds until next second boundary. */
microseconds = 1000000 - (current_time.get_microsecond());
/* If the expiration interval is the minute boundary,
* add number of milliseconds after that until next minute boundary. */
if (exp_interval == Interval.ONE_MINUTE)
{
uint seconds = 60 - current_time.get_second();
microseconds += seconds * 1000000;
}
/* Be defensive, and set the timer. */
if (microseconds <= 0)
microseconds = 1000000;
timer = Timeout.add(microseconds/1000,update_display);
}
} // End class
[ModuleInit]
public void g_io_clock_load(GLib.TypeModule module)
{
// boilerplate - all modules need this
GLib.IOExtensionPoint.implement(ValaPanel.Applet.EXTENSION_POINT,typeof(Clock),"org.valapanel.clock",10);
}
public void g_io_clock_unload(GLib.IOModule module)
{
// boilerplate - all modules need this
}
vala-panel-0.5.0/applets/core/clock/meson.build 0000664 0000000 0000000 00000000061 13736457142 0021402 0 ustar 00root root 0000000 0000000 sources = files('clock.vala')
res_exists = false
vala-panel-0.5.0/applets/core/clock/org.valapanel.clock.desktop.in 0000664 0000000 0000000 00000000074 13736457142 0025067 0 ustar 00root root 0000000 0000000 [Plugin]
Name=Clock
Description=Digital clock with calendar
vala-panel-0.5.0/applets/core/cpu/ 0000775 0000000 0000000 00000000000 13736457142 0016737 5 ustar 00root root 0000000 0000000 vala-panel-0.5.0/applets/core/cpu/cpu.c 0000664 0000000 0000000 00000027043 13736457142 0017700 0 ustar 00root root 0000000 0000000 /*
* vala-panel
* Copyright (C) 2018 Konstantin Pugin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include "cpu.h"
#define BORDER_SIZE 2
#define PANEL_HEIGHT_DEFAULT 26 /* from panel defaults */
typedef struct
{ /* Value from /proc/stat */
long long unsigned int u, n, s, i; /* User, nice, system, idle */
} cpu_stat;
/* Private context for CPU applet. */
struct _CpuApplet
{
ValaPanelApplet parent;
GdkRGBA foreground_color; /* Foreground color for drawing area */
cairo_surface_t *pixmap; /* Pixmap to be drawn on drawing area */
uint timer; /* Timer for periodic update */
float *stats_cpu; /* Ring buffer of CPU utilization values as saved CPU utilization value as
0.0..1.0*/
uint ring_cursor; /* Cursor for ring buffer */
uint pixmap_width; /* Width of drawing area pixmap; also size of ring buffer; does not
include border size */
uint pixmap_height; /* Height of drawing area pixmap; does not include border size */
cpu_stat previous_cpu_stat; /* Previous value of cpu_stat */
};
#define cpu_applet_from_da(da) VALA_PANEL_CPU_APPLET(gtk_widget_get_parent(GTK_WIDGET(da)))
#define cpu_applet_get_da(p) GTK_DRAWING_AREA(gtk_bin_get_child(GTK_BIN(p)))
G_DEFINE_DYNAMIC_TYPE(CpuApplet, cpu_applet, vala_panel_applet_get_type())
/* Redraw after timer callback or resize. */
static void redraw_pixmap(CpuApplet *c)
{
cairo_t *cr = cairo_create(c->pixmap);
GtkStyleContext *context = gtk_widget_get_style_context(GTK_WIDGET(c));
GtkStateFlags flags = gtk_widget_get_state_flags(GTK_WIDGET(c));
g_autoptr(GdkRGBA) background_color;
gtk_style_context_get(context,
flags,
GTK_STYLE_PROPERTY_BACKGROUND_COLOR,
&background_color,
NULL);
cairo_set_line_width(cr, 1.0);
/* Erase pixmap. */
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_rectangle(cr, 0, 0, c->pixmap_width, c->pixmap_height);
gdk_cairo_set_source_rgba(cr, background_color);
cairo_fill(cr);
/* Recompute pixmap. */
uint i;
uint drawing_cursor = c->ring_cursor;
gdk_cairo_set_source_rgba(cr, &c->foreground_color);
for (i = 0; i < c->pixmap_width; i++)
{
/* Draw one bar of the CPU usage graph. */
if (c->stats_cpu[drawing_cursor] != 0.0)
{
cairo_move_to(cr, i + 0.5, c->pixmap_height);
cairo_line_to(cr,
i + 0.5,
c->pixmap_height -
c->stats_cpu[drawing_cursor] * c->pixmap_height);
cairo_stroke(cr);
}
/* Increment and wrap drawing cursor. */
drawing_cursor += 1;
if (drawing_cursor >= c->pixmap_width)
drawing_cursor = 0;
}
/* check_cairo_status(cr); */
cairo_destroy(cr);
/* Redraw pixmap. */
gtk_widget_queue_draw(GTK_WIDGET(cpu_applet_get_da(c)));
}
/* Periodic timer callback. */
static int cpu_update(CpuApplet *c)
{
if (g_source_is_destroyed(g_main_current_source()))
return false;
if ((c->stats_cpu != NULL) && (c->pixmap != NULL))
{
/* Open statistics file and scan out CPU usage. */
cpu_stat cpu;
FILE *stat = fopen("/proc/stat", "r");
if (stat == NULL)
return true;
int fscanf_result =
fscanf(stat, "cpu %llu %llu %llu %llu", &cpu.u, &cpu.n, &cpu.s, &cpu.i);
fclose(stat);
/* Ensure that fscanf succeeded. */
if (fscanf_result == 4)
{
/* Compute delta from previous statistics. */
cpu_stat cpu_delta;
cpu_delta.u = cpu.u - c->previous_cpu_stat.u;
cpu_delta.n = cpu.n - c->previous_cpu_stat.n;
cpu_delta.s = cpu.s - c->previous_cpu_stat.s;
cpu_delta.i = cpu.i - c->previous_cpu_stat.i;
/* Copy current to previous. */
memcpy(&c->previous_cpu_stat, &cpu, sizeof(cpu_stat));
/* Compute user+nice+system as a fraction of total.
* Introduce this sample to ring buffer, increment and wrap ring buffer
* cursor. */
float cpu_uns = cpu_delta.u + cpu_delta.n + cpu_delta.s;
c->stats_cpu[c->ring_cursor] = cpu_uns / (cpu_uns + cpu_delta.i);
c->ring_cursor += 1;
if (c->ring_cursor >= c->pixmap_width)
c->ring_cursor = 0;
/* Redraw with the new sample. */
redraw_pixmap(c);
}
}
return G_SOURCE_CONTINUE;
}
/* Handler for configure_event on drawing area. */
static bool configure_event(GtkWidget *widget, G_GNUC_UNUSED GdkEventConfigure *event, CpuApplet *c)
{
GtkAllocation allocation;
gtk_widget_get_allocation(widget, &allocation);
/* Allocate pixmap and statistics buffer without border pixels. */
uint new_pixmap_width = (uint)MAX(allocation.width - BORDER_SIZE * 2, 0);
uint new_pixmap_height = (uint)MAX(allocation.height - BORDER_SIZE * 2, 0);
if ((new_pixmap_width > 0) && (new_pixmap_height > 0))
{
/* If statistics buffer does not exist or it changed size, reallocate and preserve
* existing data. */
if ((c->stats_cpu == NULL) || (new_pixmap_width != c->pixmap_width))
{
float *new_stats_cpu = g_new0(float, new_pixmap_width);
if (c->stats_cpu != NULL)
{
if (new_pixmap_width > c->pixmap_width)
{
/* New allocation is larger.
* Introduce new "oldest" samples of zero following the
* cursor. */
memcpy(&new_stats_cpu[0],
&c->stats_cpu[0],
c->ring_cursor * sizeof(float));
memcpy(&new_stats_cpu[new_pixmap_width - c->pixmap_width +
c->ring_cursor],
&c->stats_cpu[c->ring_cursor],
(c->pixmap_width - c->ring_cursor) * sizeof(float));
}
else if (c->ring_cursor <= new_pixmap_width)
{
/* New allocation is smaller, but still larger than the ring
* buffer cursor.
* Discard the oldest samples following the cursor. */
memcpy(&new_stats_cpu[0],
&c->stats_cpu[0],
c->ring_cursor * sizeof(float));
memcpy(&new_stats_cpu[c->ring_cursor],
&c->stats_cpu[c->pixmap_width - new_pixmap_width +
c->ring_cursor],
(new_pixmap_width - c->ring_cursor) * sizeof(float));
}
else
{
/* New allocation is smaller, and also smaller than the ring
* buffer cursor.
* Discard all oldest samples following the ring buffer
* cursor and additional samples at the beginning of the
* buffer. */
memcpy(&new_stats_cpu[0],
&c->stats_cpu[c->ring_cursor - new_pixmap_width],
new_pixmap_width * sizeof(float));
c->ring_cursor = 0;
}
g_free(c->stats_cpu);
}
c->stats_cpu = new_stats_cpu;
}
/* Allocate or reallocate pixmap. */
c->pixmap_width = new_pixmap_width;
c->pixmap_height = new_pixmap_height;
if (c->pixmap)
cairo_surface_destroy(c->pixmap);
c->pixmap = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
c->pixmap_width,
c->pixmap_height);
/* check_cairo_surface_status(&c->pixmap); */
/* Redraw pixmap at the new size. */
redraw_pixmap(c);
}
return true;
}
/* Handler for draw on drawing area. */
static bool draw(G_GNUC_UNUSED GtkWidget *widget, cairo_t *cr, CpuApplet *c)
{
/* Draw the requested part of the pixmap onto the drawing area.
* Translate it in both x and y by the border size. */
if (c->pixmap != NULL)
{
GtkStyleContext *context = gtk_widget_get_style_context(GTK_WIDGET(c));
GtkStateFlags flags = gtk_widget_get_state_flags(GTK_WIDGET(c));
g_autoptr(GdkRGBA) background_color;
gtk_style_context_get(context,
flags,
GTK_STYLE_PROPERTY_BACKGROUND_COLOR,
&background_color,
NULL);
gdk_cairo_set_source_rgba(cr, background_color);
cairo_set_source_surface(cr, c->pixmap, BORDER_SIZE, BORDER_SIZE);
cairo_paint(cr);
/* check_cairo_status(cr); */
}
return false;
}
static void on_height_change(GObject *owner, G_GNUC_UNUSED GParamSpec *pspec, void *data)
{
GtkWidget *da = GTK_WIDGET(data);
uint height;
g_object_get(owner, VP_KEY_HEIGHT, &height, NULL);
gtk_widget_set_size_request(da, height > 40 ? height : 40, height);
}
/* Applet widget constructor. */
CpuApplet *cpu_applet_new(ValaPanelToplevel *toplevel, GSettings *settings, const char *uuid)
{
/* Allocate applet context*/
CpuApplet *c = VALA_PANEL_CPU_APPLET(
vala_panel_applet_construct(cpu_applet_get_type(), toplevel, settings, uuid));
return c;
}
static void cpu_applet_constructed(GObject *obj)
{
G_OBJECT_CLASS(cpu_applet_parent_class)->constructed(obj);
CpuApplet *c = VALA_PANEL_CPU_APPLET(obj);
ValaPanelToplevel *toplevel = vala_panel_applet_get_toplevel(VALA_PANEL_APPLET(c));
/* Allocate drawing area as a child of top level widget. */
GtkDrawingArea *da = GTK_DRAWING_AREA(gtk_drawing_area_new());
gtk_widget_add_events(GTK_WIDGET(da),
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
GDK_BUTTON_MOTION_MASK);
on_height_change(G_OBJECT(toplevel), NULL, da);
gtk_container_add(GTK_CONTAINER(c), GTK_WIDGET(da));
GtkStyleContext *context = gtk_widget_get_style_context(GTK_WIDGET(toplevel));
GtkStateFlags flags = gtk_widget_get_state_flags(GTK_WIDGET(toplevel));
gtk_style_context_get_color(context, flags, &c->foreground_color);
/* Connect signals. */
g_signal_connect(G_OBJECT(toplevel),
"notify::" VP_KEY_HEIGHT,
G_CALLBACK(on_height_change),
(gpointer)da);
g_signal_connect(G_OBJECT(da), "configure-event", G_CALLBACK(configure_event), (gpointer)c);
g_signal_connect(G_OBJECT(da), "draw", G_CALLBACK(draw), (gpointer)c);
/* Show the widget. Connect a timer to refresh the statistics. */
gtk_widget_show(GTK_WIDGET(da));
c->timer = g_timeout_add(1500, (GSourceFunc)cpu_update, (gpointer)c);
gtk_widget_show(GTK_WIDGET(c));
}
/* Plugin destructor. */
static void cpu_applet_dispose(GObject *user_data)
{
CpuApplet *c = VALA_PANEL_CPU_APPLET(user_data);
/* Disconnect the timer. */
if (c->timer)
{
g_source_remove(c->timer);
c->timer = 0;
}
/* Deallocate memory. */
g_clear_pointer(&c->pixmap, cairo_surface_destroy);
g_clear_pointer(&c->stats_cpu, g_free);
G_OBJECT_CLASS(cpu_applet_parent_class)->dispose(user_data);
}
static void cpu_applet_init(G_GNUC_UNUSED CpuApplet *self)
{
}
static void cpu_applet_class_init(CpuAppletClass *klass)
{
G_OBJECT_CLASS(klass)->constructed = cpu_applet_constructed;
G_OBJECT_CLASS(klass)->dispose = cpu_applet_dispose;
}
static void cpu_applet_class_finalize(G_GNUC_UNUSED CpuAppletClass *klass)
{
}
/*
* IO Module functions
*/
void g_io_cpu_load(GTypeModule *module)
{
g_return_if_fail(module != NULL);
cpu_applet_register_type(module);
g_io_extension_point_implement(VALA_PANEL_APPLET_EXTENSION_POINT,
cpu_applet_get_type(),
"org.valapanel.cpu",
10);
}
void g_io_cpu_unload(GIOModule *module)
{
g_return_if_fail(module != NULL);
}
vala-panel-0.5.0/applets/core/cpu/cpu.h 0000664 0000000 0000000 00000001700 13736457142 0017675 0 ustar 00root root 0000000 0000000 /*
* vala-panel
* Copyright (C) 2018 Konstantin Pugin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#ifndef VALAPANELCPU_H
#define VALAPANELCPU_H
#include "client.h"
G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE(CpuApplet, cpu_applet, VALA_PANEL, CPU_APPLET, ValaPanelApplet)
G_END_DECLS
#endif // VALAPANELGENMON_H
vala-panel-0.5.0/applets/core/cpu/meson.build 0000664 0000000 0000000 00000000075 13736457142 0021103 0 ustar 00root root 0000000 0000000 sources = files(
'cpu.c',
'cpu.h'
)
res_exists = false
vala-panel-0.5.0/applets/core/cpu/org.valapanel.cpu.desktop.in 0000664 0000000 0000000 00000000076 13736457142 0024261 0 ustar 00root root 0000000 0000000 [Plugin]
Name=CPU Graph
Description=Draws CPU graph on panel.
vala-panel-0.5.0/applets/core/dirmenu/ 0000775 0000000 0000000 00000000000 13736457142 0017613 5 ustar 00root root 0000000 0000000 vala-panel-0.5.0/applets/core/dirmenu/dirmenu.vala 0000664 0000000 0000000 00000017565 13736457142 0022141 0 ustar 00root root 0000000 0000000 /*
* vala-panel
* Copyright (C) 2015 Konstantin Pugin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
using ValaPanel;
using Gtk;
public class Dirmenu: Applet
{
private struct DirectorySort
{
string dirname;
string collate_key;
}
private const string DIR = "dir-path";
private const string ICON = "icon-name";
private const string LABEL = "caption";
internal string dir_path
{get; set;}
internal string caption
{get; set;}
internal string icon_name
{get; set;}
public Dirmenu(ValaPanel.Toplevel toplevel,
GLib.Settings? settings,
string number)
{
base(toplevel,settings,number);
}
public override void constructed()
{
(this.action_group.lookup_action(AppletAction.CONFIGURE) as SimpleAction).set_enabled(true);
var button = new MenuButton();
var img = new Image();
settings.bind(DIR,this,DIR,SettingsBindFlags.GET);
settings.bind(ICON,this,ICON,SettingsBindFlags.GET);
settings.bind(LABEL,this,LABEL,SettingsBindFlags.GET);
setup_icon(img,set_icon(),toplevel);
setup_button(button as Button,img,caption);
button.set_popup(create_menu(dir_path,false));
this.notify.connect((pspec)=>{
if (pspec.name == ICON)
(button.image as Image).set_from_gicon(set_icon(),IconSize.INVALID);
if (pspec.name == LABEL)
button.set_label(caption);
if (pspec.name == DIR)
button.set_popup(create_menu(dir_path,false));
});
this.add(button);
button.show();
this.show();
}
private Icon set_icon(){
Icon? icon = null;
try
{
icon = Icon.new_for_string(icon_name);
} catch (GLib.Error e) {}
return icon ?? new ThemedIcon.with_default_fallbacks("system-file-manager");
}
private Gtk.Menu create_menu(string directory,bool at_top)
{
/* Create a menu. */
var menu = new Gtk.Menu();
menu.set_data("path", directory);
SList dir_list = new SList();
/* Scan the specified directory to populate the menu with its subdirectories. */
Dir? dir = null;
try {
dir = Dir.open(directory);
string? name = null;
while ((name = dir.read_name()) != null)
{
/* Omit hidden files. */
if (name[0] != '.')
{
string full = Path.build_filename(directory, name);
if (FileUtils.test(full, FileTest.IS_DIR))
{
DirectorySort cur = DirectorySort();
cur.dirname = Filename.display_name(name);
cur.collate_key = cur.dirname.collate_key();
dir_list.insert_sorted(cur,(a,b)=>{return strcmp(a.collate_key,b.collate_key);});
}
}
}
} catch (Error e) {stderr.printf("%s\n",e.message);}
/* The sorted directory name list is complete. Loop to create the menu. */
foreach(var cursor in dir_list)
{
/* Create and initialize menu item. */
Gtk.MenuItem item = new Gtk.MenuItem();
var box = new Box(Orientation.HORIZONTAL,10);
var img = new Image.from_gicon(new ThemedIcon.with_default_fallbacks("folder-symbolic"),IconSize.MENU);
img.show();
box.pack_start(img,false,true);
var lbl = new Label(cursor.dirname);
box.pack_start(lbl,false,true);
lbl.show();
item.add(box);
box.show();
Gtk.Menu dummy = new Gtk.Menu();
item.set_submenu(dummy);
item.show();
menu.append(item);
/* Unlink and free sorted directory name element, but reuse the directory name string. */
item.set_data("name",cursor.dirname);
/* Connect signals. */
item.select.connect(()=>{
if (item.get_submenu() != null)
{
/* On first reference, populate the submenu using the parent directory and the item directory name. */
string dpath = item.get_submenu().get_data("path");
if (dpath == null)
{
dpath = Path.build_filename(
item.get_parent().get_data("path"),
item.get_data("name"));
item.set_submenu(create_menu(dpath, true));
}
}
});
item.deselect.connect(()=>{item.set_submenu(new Gtk.Menu());});
}
/* Create "Open" and "Open in Terminal" items. */
var item = new Gtk.MenuItem.with_mnemonic( _("_Open") );
item.activate.connect(()=>{
try {
GLib.AppInfo.launch_default_for_uri(Filename.to_uri(directory),
Gdk.Display.get_default().get_app_launch_context());
} catch(GLib.Error e){stderr.printf("%s",e.message);}
});
item.show();
var term = new Gtk.MenuItem.with_mnemonic( _("Open in _Terminal") );
term.activate.connect(()=>{launch_terminal(directory);});
term.show();
/* Insert or append based on caller's preference. */
if (at_top)
{
menu.insert(new SeparatorMenuItem(), 0);
menu.insert(term, 0);
menu.insert(item, 0);
}
else {
menu.append(new SeparatorMenuItem());
menu.append(term);
menu.append(item);
}
/* Show the menu and return. */
menu.show();
return menu;
}
private void launch_terminal(string dir)
{
string? command;
string true_dir = dir;
toplevel.application.get("terminal-command",out command);
if (!Path.is_absolute(dir))
true_dir = Posix.realpath(dir);
try
{
string[] argv = command.split(" ");
var envp = Environ.set_variable(Environ.get(),"PWD",true_dir,true);
Process.spawn_async(true_dir,argv,envp,SpawnFlags.SEARCH_PATH,null,null);
}
catch (GLib.Error e){stderr.printf("Cannot launch terminal: %s\n",e.message);}
}
public override bool button_release_event(Gdk.EventButton e)
{
if (e.button == 2)
launch_terminal(dir_path);
return false;
}
public override Widget get_settings_ui()
{
return Configurator.generic_config_widget(this.settings,
_("Directory"), DIR, GenericConfigType.DIRECTORY,
_("Label"), LABEL, GenericConfigType.STR,
_("Icon"), ICON, GenericConfigType.FILE_ENTRY);
}
} // End class
[ModuleInit]
public void g_io_dirmenu_load(GLib.TypeModule module)
{
// boilerplate - all modules need this
GLib.IOExtensionPoint.implement(ValaPanel.Applet.EXTENSION_POINT,typeof(Dirmenu),"org.valapanel.dirmenu",10);
}
public void g_io_dirmenu_unload(GLib.IOModule module)
{
// boilerplate - all modules need this
}
vala-panel-0.5.0/applets/core/dirmenu/meson.build 0000664 0000000 0000000 00000000063 13736457142 0021754 0 ustar 00root root 0000000 0000000 sources = files('dirmenu.vala')
res_exists = false
vala-panel-0.5.0/applets/core/dirmenu/org.valapanel.dirmenu.desktop.in 0000664 0000000 0000000 00000000147 13736457142 0026010 0 ustar 00root root 0000000 0000000 [Plugin]
Name=Directory menu
Description=This menu shows filesystem hierarchy, started from given dir.
vala-panel-0.5.0/applets/core/kbled/ 0000775 0000000 0000000 00000000000 13736457142 0017231 5 ustar 00root root 0000000 0000000 vala-panel-0.5.0/applets/core/kbled/images/ 0000775 0000000 0000000 00000000000 13736457142 0020476 5 ustar 00root root 0000000 0000000 vala-panel-0.5.0/applets/core/kbled/images/capslock-off.png 0000664 0000000 0000000 00000007567 13736457142 0023572 0 ustar 00root root 0000000 0000000 PNG
IHDR w= pHYs
OiCCPPhotoshop ICC profile xڝSgTS=BKKoR RB&*! J!QEEȠQ,
!{kּ>H3Q5B.@
$p d!s# ~<<+" x M0B\t8K @zB @F&S