Compare commits
23 Commits
4da1db3bd4
...
master
Author | SHA1 | Date | |
---|---|---|---|
f1281858d3 | |||
bdd6bae1a9 | |||
b3d6ba9a54 | |||
6828400a77 | |||
a0456516b5 | |||
d2ca1732f1 | |||
2a88d12bfa | |||
363d0d1678 | |||
be7a573bef | |||
2775e497f5 | |||
12014a121d | |||
8c70733b9b | |||
1294edf250 | |||
443f323597 | |||
7dab18e121 | |||
224252807a | |||
e598847994 | |||
b10cfab3ba | |||
e6515cca06 | |||
3b22827e4f | |||
2c5338f4bf | |||
24f47dfd7f | |||
8020954fed |
27
README.md
27
README.md
@ -1,3 +1,30 @@
|
|||||||
# diya-shell
|
# diya-shell
|
||||||
|
|
||||||
Wayland shell for diyac wayland compositor
|
Wayland shell for diyac wayland compositor
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
|
||||||
|
## Theme
|
||||||
|
|
||||||
|
Default theme can be set using the envar `DIYA_DEFAULT_THEME`, this will cause the shell searching for CSS file theme in
|
||||||
|
`/home/$USER/.themes/<name>/gtk-4.0/gtk.css`:
|
||||||
|
|
||||||
|
* diya-shell: will looking for file: `dev.iohub.diya.session-shell.css`
|
||||||
|
* diya-login-shell: will looking for file: `dev.iohub.diya.login-shell.css`
|
||||||
|
|
||||||
|
# Virtual keyboard layout
|
||||||
|
|
||||||
|
Default virtual keyboard keymap can be set via the `DIYA_VKB_KEYMAP` environment variable. When created virtual keyboard,
|
||||||
|
the shell will search for keymap file in: `/home/$USER/.config/diya/xkb/${DIYA_VKB_KEYMAP}.keymap`
|
||||||
|
|
||||||
|
|
||||||
|
# Launch terminal based application
|
||||||
|
|
||||||
|
create file in `/home/$USER/bin/xdg-terminal-exec` with:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
#! /bin/sh
|
||||||
|
foot $@
|
||||||
|
```
|
||||||
|
|
||||||
|
this allows gtk4-launch to launch a terminal based application
|
31
meson.build
31
meson.build
@ -1,6 +1,6 @@
|
|||||||
project('diya-shell',
|
project('diya-shell',
|
||||||
['c'],
|
['c'],
|
||||||
version: '0.1.0',
|
version: '0.1.2',
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
meson_version: '>=0.58.0',
|
meson_version: '>=0.58.0',
|
||||||
default_options: ['c_std=gnu11', 'warning_level=3'])
|
default_options: ['c_std=gnu11', 'warning_level=3'])
|
||||||
@ -12,6 +12,7 @@ add_project_arguments(
|
|||||||
'-Wno-pedantic',
|
'-Wno-pedantic',
|
||||||
'-Werror=implicit-function-declaration',
|
'-Werror=implicit-function-declaration',
|
||||||
'-Werror=return-type',
|
'-Werror=return-type',
|
||||||
|
'-D__SHELL_VERSION__="@0@"'.format(meson.project_version())
|
||||||
],
|
],
|
||||||
language: 'c')
|
language: 'c')
|
||||||
|
|
||||||
@ -36,8 +37,10 @@ wayland_targets=[]
|
|||||||
|
|
||||||
wl_protocols = [
|
wl_protocols = [
|
||||||
wl_protocol_dir / 'staging/ext-session-lock/ext-session-lock-v1',
|
wl_protocol_dir / 'staging/ext-session-lock/ext-session-lock-v1',
|
||||||
|
wl_protocol_dir / 'staging/ext-idle-notify/ext-idle-notify-v1',
|
||||||
'protocols/wlr-foreign-toplevel-management-unstable-v1',
|
'protocols/wlr-foreign-toplevel-management-unstable-v1',
|
||||||
'protocols/virtual-keyboard-unstable-v1'
|
'protocols/virtual-keyboard-unstable-v1',
|
||||||
|
'protocols/wlr-output-power-management-unstable-v1',
|
||||||
]
|
]
|
||||||
|
|
||||||
foreach proto : wl_protocols
|
foreach proto : wl_protocols
|
||||||
@ -52,11 +55,19 @@ endforeach
|
|||||||
|
|
||||||
gnome=import('gnome')
|
gnome=import('gnome')
|
||||||
|
|
||||||
|
incdir = include_directories([
|
||||||
|
'src'
|
||||||
|
])
|
||||||
|
|
||||||
base = [
|
base = [
|
||||||
'src/base.c',
|
'src/base.c',
|
||||||
'src/shell.c',
|
'src/shell.c',
|
||||||
'src/wayland.c',
|
'src/wayland.c',
|
||||||
|
'src/input.c',
|
||||||
'src/virtual-keyboard.c',
|
'src/virtual-keyboard.c',
|
||||||
|
'src/widgets/virtual-keyboard-widgets.c',
|
||||||
|
'src/files-monitor.c',
|
||||||
|
'src/idle.c',
|
||||||
wayland_targets
|
wayland_targets
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -67,17 +78,22 @@ dm_src = [
|
|||||||
'src/session-shell.c',
|
'src/session-shell.c',
|
||||||
'src/foreign.c',
|
'src/foreign.c',
|
||||||
'src/session-lock.c',
|
'src/session-lock.c',
|
||||||
'src/session.c']
|
'src/session.c',
|
||||||
|
'src/widgets/base-widgets.c',
|
||||||
|
'src/widgets/taskbar-widget.c',
|
||||||
|
'src/widgets/dashboard-widget.c',
|
||||||
|
]
|
||||||
|
|
||||||
buil_dep = [gtk, gtk_layer_shell, wayland_client, xkbcommon]
|
buil_dep = [gtk, gtk_layer_shell, wayland_client, xkbcommon]
|
||||||
|
|
||||||
session_resource = gnome.compile_resources('session-resources','resources/session-shell/gresource.xml')
|
session_resource = gnome.compile_resources('session-resources','resources/gresource-session.xml')
|
||||||
|
|
||||||
executable(
|
executable(
|
||||||
'diya-shell',
|
'diya-shell',
|
||||||
dm_src,
|
dm_src,
|
||||||
session_resource,
|
session_resource,
|
||||||
dependencies: buil_dep)
|
dependencies: buil_dep,
|
||||||
|
include_directories : incdir)
|
||||||
|
|
||||||
login_src = [
|
login_src = [
|
||||||
base,
|
base,
|
||||||
@ -85,10 +101,11 @@ login_src = [
|
|||||||
'src/login.c'
|
'src/login.c'
|
||||||
]
|
]
|
||||||
|
|
||||||
login_resource = gnome.compile_resources('login-resources','resources/login-shell/gresource.xml')
|
login_resource = gnome.compile_resources('login-resources','resources/gresource-login.xml')
|
||||||
|
|
||||||
executable(
|
executable(
|
||||||
'diya-login-shell',
|
'diya-login-shell',
|
||||||
login_src,
|
login_src,
|
||||||
login_resource,
|
login_resource,
|
||||||
dependencies: buil_dep)
|
dependencies: buil_dep,
|
||||||
|
include_directories : incdir)
|
128
protocols/wlr-output-power-management-unstable-v1.xml
Normal file
128
protocols/wlr-output-power-management-unstable-v1.xml
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<protocol name="wlr_output_power_management_unstable_v1">
|
||||||
|
<copyright>
|
||||||
|
Copyright © 2019 Purism SPC
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice (including the next
|
||||||
|
paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
</copyright>
|
||||||
|
|
||||||
|
<description summary="Control power management modes of outputs">
|
||||||
|
This protocol allows clients to control power management modes
|
||||||
|
of outputs that are currently part of the compositor space. The
|
||||||
|
intent is to allow special clients like desktop shells to power
|
||||||
|
down outputs when the system is idle.
|
||||||
|
|
||||||
|
To modify outputs not currently part of the compositor space see
|
||||||
|
wlr-output-management.
|
||||||
|
|
||||||
|
Warning! The protocol described in this file is experimental and
|
||||||
|
backward incompatible changes may be made. Backward compatible changes
|
||||||
|
may be added together with the corresponding interface version bump.
|
||||||
|
Backward incompatible changes are done by bumping the version number in
|
||||||
|
the protocol and interface names and resetting the interface version.
|
||||||
|
Once the protocol is to be declared stable, the 'z' prefix and the
|
||||||
|
version number in the protocol and interface names are removed and the
|
||||||
|
interface version number is reset.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<interface name="zwlr_output_power_manager_v1" version="1">
|
||||||
|
<description summary="manager to create per-output power management">
|
||||||
|
This interface is a manager that allows creating per-output power
|
||||||
|
management mode controls.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<request name="get_output_power">
|
||||||
|
<description summary="get a power management for an output">
|
||||||
|
Create an output power management mode control that can be used to
|
||||||
|
adjust the power management mode for a given output.
|
||||||
|
</description>
|
||||||
|
<arg name="id" type="new_id" interface="zwlr_output_power_v1"/>
|
||||||
|
<arg name="output" type="object" interface="wl_output"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="destroy the manager">
|
||||||
|
All objects created by the manager will still remain valid, until their
|
||||||
|
appropriate destroy request has been called.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<interface name="zwlr_output_power_v1" version="1">
|
||||||
|
<description summary="adjust power management mode for an output">
|
||||||
|
This object offers requests to set the power management mode of
|
||||||
|
an output.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<enum name="mode">
|
||||||
|
<entry name="off" value="0"
|
||||||
|
summary="Output is turned off."/>
|
||||||
|
<entry name="on" value="1"
|
||||||
|
summary="Output is turned on, no power saving"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<enum name="error">
|
||||||
|
<entry name="invalid_mode" value="1" summary="nonexistent power save mode"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<request name="set_mode">
|
||||||
|
<description summary="Set an outputs power save mode">
|
||||||
|
Set an output's power save mode to the given mode. The mode change
|
||||||
|
is effective immediately. If the output does not support the given
|
||||||
|
mode a failed event is sent.
|
||||||
|
</description>
|
||||||
|
<arg name="mode" type="uint" enum="mode" summary="the power save mode to set"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<event name="mode">
|
||||||
|
<description summary="Report a power management mode change">
|
||||||
|
Report the power management mode change of an output.
|
||||||
|
|
||||||
|
The mode event is sent after an output changed its power
|
||||||
|
management mode. The reason can be a client using set_mode or the
|
||||||
|
compositor deciding to change an output's mode.
|
||||||
|
This event is also sent immediately when the object is created
|
||||||
|
so the client is informed about the current power management mode.
|
||||||
|
</description>
|
||||||
|
<arg name="mode" type="uint" enum="mode"
|
||||||
|
summary="the output's new power management mode"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="failed">
|
||||||
|
<description summary="object no longer valid">
|
||||||
|
This event indicates that the output power management mode control
|
||||||
|
is no longer valid. This can happen for a number of reasons,
|
||||||
|
including:
|
||||||
|
- The output doesn't support power management
|
||||||
|
- Another client already has exclusive power management mode control
|
||||||
|
for this output
|
||||||
|
- The output disappeared
|
||||||
|
|
||||||
|
Upon receiving this event, the client should destroy this object.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="destroy this power management">
|
||||||
|
Destroys the output power management mode control object.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
</protocol>
|
21
resources/css/login-shell.css
Normal file
21
resources/css/login-shell.css
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
@import url("resource:///dev/iohub/diya/shell/css/virtual-keyboard.css");
|
||||||
|
|
||||||
|
#diya_login_shell
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#diya_login_shell label.diya-login-header {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#diya_login_shell label.diya-login-status {
|
||||||
|
font-size: 12px;
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
#diya_login_shell button.diya-btn-show-vkb
|
||||||
|
{
|
||||||
|
color: gray;
|
||||||
|
min-width: 0px;
|
||||||
|
}
|
21
resources/css/session-shell.css
Normal file
21
resources/css/session-shell.css
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
@import url("resource:///dev/iohub/diya/shell/css/virtual-keyboard.css");
|
||||||
|
|
||||||
|
diya-taskbar
|
||||||
|
{
|
||||||
|
background-color: orange;
|
||||||
|
}
|
||||||
|
|
||||||
|
diya-dashboard
|
||||||
|
{
|
||||||
|
background-color: lightgray;
|
||||||
|
}
|
||||||
|
|
||||||
|
#diya_shell_background
|
||||||
|
{
|
||||||
|
background-image:url("file:///etc/xdg/labwc/wpp.jpg");
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
flowbox flowboxchild {
|
||||||
|
border: 5px solid black;
|
||||||
|
}
|
48
resources/css/virtual-keyboard.css
Normal file
48
resources/css/virtual-keyboard.css
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
diya-vkb
|
||||||
|
{
|
||||||
|
background-color: transparent;
|
||||||
|
/* border: 1px solid orangered; */
|
||||||
|
}
|
||||||
|
|
||||||
|
diya-vkb-button
|
||||||
|
{
|
||||||
|
background-color: white;
|
||||||
|
border: 1px solid #CDC7C2;
|
||||||
|
border-radius: 3px;
|
||||||
|
min-width: 30px;
|
||||||
|
min-height: 30px;
|
||||||
|
box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.19);
|
||||||
|
}
|
||||||
|
|
||||||
|
diya-vkb-button.active
|
||||||
|
{
|
||||||
|
background-color: #E7E6E2;
|
||||||
|
}
|
||||||
|
|
||||||
|
diya-vkb-button:hover
|
||||||
|
{
|
||||||
|
background-color: #E7E6E2;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
.diya-vkb-btn label {
|
||||||
|
border: 1px solid #b81f2b;
|
||||||
|
|
||||||
|
}*/
|
||||||
|
|
||||||
|
diya-vkb-button label.shift-level-1 {
|
||||||
|
color: black;
|
||||||
|
padding-top: 2px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
diya-vkb-button label.shift-level-2 {
|
||||||
|
color: gray;
|
||||||
|
font-size: 9px;
|
||||||
|
padding-left: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
diya-vkb-button label.shift-level-3 {
|
||||||
|
color: gray;
|
||||||
|
font-size: 9px;
|
||||||
|
padding-right: 3px;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
10
resources/gresource-login.xml
Normal file
10
resources/gresource-login.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<gresources>
|
||||||
|
<gresource prefix="/dev/iohub/diya/shell/css">
|
||||||
|
<file alias="dev.iohub.diya.login-shell.css">resources/css/login-shell.css</file>
|
||||||
|
<file alias="virtual-keyboard.css">resources/css/virtual-keyboard.css</file>
|
||||||
|
</gresource>
|
||||||
|
<gresource prefix="/dev/iohub/diya/shell/vkb">
|
||||||
|
<file alias="default.keymap">resources/vkb/default.keymap</file>
|
||||||
|
</gresource>
|
||||||
|
</gresources>
|
17
resources/gresource-session.xml
Normal file
17
resources/gresource-session.xml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<gresources>
|
||||||
|
<gresource prefix="/dev/iohub/diya/shell/vkb">
|
||||||
|
<file alias="default.keymap">resources/vkb/default.keymap</file>
|
||||||
|
</gresource>
|
||||||
|
<gresource prefix="/dev/iohub/diya/shell/ui">
|
||||||
|
<file alias="dashboard.ui">resources/ui/dashboard.ui</file>
|
||||||
|
<file alias="taskbar.ui">resources/ui/taskbar.ui</file>
|
||||||
|
</gresource>
|
||||||
|
<gresource prefix="/dev/iohub/diya/shell/css">
|
||||||
|
<file alias="dev.iohub.diya.session-shell.css">resources/css/session-shell.css</file>
|
||||||
|
<file alias="virtual-keyboard.css">resources/css/virtual-keyboard.css</file>
|
||||||
|
</gresource>
|
||||||
|
<gresource prefix="/dev/iohub/diya/shell/icons/scalable">
|
||||||
|
<file alias="gear">resources/icons/scalable/gear.svg</file>
|
||||||
|
</gresource>
|
||||||
|
</gresources>
|
1
resources/icons/scalable/gear.svg
Normal file
1
resources/icons/scalable/gear.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48px" height="48px"><linearGradient id="L4rKfs~Qrm~k0Pk8MRsoza" x1="32.012" x2="15.881" y1="32.012" y2="15.881" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset=".242" stop-color="#f2f2f2"/><stop offset="1" stop-color="#ccc"/></linearGradient><circle cx="24" cy="24" r="11.5" fill="url(#L4rKfs~Qrm~k0Pk8MRsoza)"/><linearGradient id="L4rKfs~Qrm~k0Pk8MRsozb" x1="17.45" x2="28.94" y1="17.45" y2="28.94" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#0d61a9"/><stop offset=".363" stop-color="#0e5fa4"/><stop offset=".78" stop-color="#135796"/><stop offset="1" stop-color="#16528c"/></linearGradient><circle cx="24" cy="24" r="7" fill="url(#L4rKfs~Qrm~k0Pk8MRsozb)"/><linearGradient id="L4rKfs~Qrm~k0Pk8MRsozc" x1="5.326" x2="38.082" y1="5.344" y2="38.099" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#889097"/><stop offset=".331" stop-color="#848c94"/><stop offset=".669" stop-color="#78828b"/><stop offset="1" stop-color="#64717c"/></linearGradient><path fill="url(#L4rKfs~Qrm~k0Pk8MRsozc)" d="M43.407,19.243c-2.389-0.029-4.702-1.274-5.983-3.493c-1.233-2.136-1.208-4.649-0.162-6.693 c-2.125-1.887-4.642-3.339-7.43-4.188C28.577,6.756,26.435,8,24,8s-4.577-1.244-5.831-3.131c-2.788,0.849-5.305,2.301-7.43,4.188 c1.046,2.044,1.071,4.557-0.162,6.693c-1.281,2.219-3.594,3.464-5.983,3.493C4.22,20.77,4,22.358,4,24 c0,1.284,0.133,2.535,0.364,3.752c2.469-0.051,4.891,1.208,6.213,3.498c1.368,2.37,1.187,5.204-0.22,7.345 c2.082,1.947,4.573,3.456,7.34,4.375C18.827,40.624,21.221,39,24,39s5.173,1.624,6.303,3.971c2.767-0.919,5.258-2.428,7.34-4.375 c-1.407-2.141-1.588-4.975-0.22-7.345c1.322-2.29,3.743-3.549,6.213-3.498C43.867,26.535,44,25.284,44,24 C44,22.358,43.78,20.77,43.407,19.243z M24,34.5c-5.799,0-10.5-4.701-10.5-10.5c0-5.799,4.701-10.5,10.5-10.5S34.5,18.201,34.5,24 C34.5,29.799,29.799,34.5,24,34.5z"/></svg>
|
After Width: | Height: | Size: 1.9 KiB |
@ -1,7 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<gresources>
|
|
||||||
<gresource prefix="/dev/iohub/diya/shell">
|
|
||||||
<file alias="login-shell.css">resources/login-shell/login-shell.css</file>
|
|
||||||
<file alias="default.keymap">resources/default.keymap</file>
|
|
||||||
</gresource>
|
|
||||||
</gresources>
|
|
@ -1,9 +0,0 @@
|
|||||||
.header {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status {
|
|
||||||
font-size: 12px;
|
|
||||||
color: red;
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<gresources>
|
|
||||||
<gresource prefix="/dev/iohub/diya/shell">
|
|
||||||
<file alias="default.keymap">resources/default.keymap</file>
|
|
||||||
</gresource>
|
|
||||||
</gresources>
|
|
94
resources/ui/dashboard.ui
Normal file
94
resources/ui/dashboard.ui
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<template class="DiyaDashboardWidget" parent="DiyaShellWindow">
|
||||||
|
<!--property name="title" translatable="yes">Example Application</property-->
|
||||||
|
<!--property name="default-width">600</property>
|
||||||
|
<property name="default-height">400</property-->
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkRevealer" id="revealer">
|
||||||
|
<property name="transition-type">slide-up</property>
|
||||||
|
<property name="reveal-child">0</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="header">
|
||||||
|
<property name="orientation">horizontal</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkSearchEntry" id="search_entry">
|
||||||
|
<property name="hexpand">1</property>
|
||||||
|
<signal name="search-changed" handler="diya_dashboard_search_text_changed"/>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkMenuButton" id="gears">
|
||||||
|
<property name="direction">none</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkStack" id="stack">
|
||||||
|
<property name="vexpand">1</property>
|
||||||
|
<property name="hexpand">1</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkStackPage">
|
||||||
|
<property name="name">app_list</property>
|
||||||
|
<property name="title">Application list</property>
|
||||||
|
<property name="child">
|
||||||
|
<object class="GtkScrolledWindow" id="sidebar-sw">
|
||||||
|
<property name="hscrollbar-policy">never</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkFlowBox" id="app_list_box">
|
||||||
|
<property name="activate-on-single-click">1</property>
|
||||||
|
<signal name="child-activated" handler="diya_dashboard_app_launch"/>
|
||||||
|
</object>
|
||||||
|
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkStackPage">
|
||||||
|
<property name="name">search_list</property>
|
||||||
|
<property name="title">Search</property>
|
||||||
|
<property name="child">
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="label">second stack child</property>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
<child type="title">
|
||||||
|
<object class="GtkStackSwitcher" id="tabs">
|
||||||
|
<property name="stack">stack</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
<!--child>
|
||||||
|
<object class="GtkBox" id="taskbar">
|
||||||
|
<property name="orientation">horizontal</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="btn_launch">
|
||||||
|
<property name="visible">1</property>
|
||||||
|
<property name="label" translatable="yes">Terminal</property>
|
||||||
|
<signal name="clicked" handler="diya_dashboard_launch"/>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child-->
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</template>
|
||||||
|
</interface>
|
34
resources/ui/taskbar.ui
Normal file
34
resources/ui/taskbar.ui
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<template class="DiyaTaskbarWidget" parent="DiyaShellWindow">
|
||||||
|
<!--property name="title" translatable="yes">Example Application</property-->
|
||||||
|
<!--property name="default-width">600</property>
|
||||||
|
<property name="default-height">400</property-->
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="taskbar">
|
||||||
|
<property name="hexpand">1</property>
|
||||||
|
<property name="orientation">horizontal</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkToggleButton" id="btn_toggle">
|
||||||
|
<property name="visible">1</property>
|
||||||
|
<property name="label" translatable="yes">Diya</property>
|
||||||
|
<!--signal name="toggled" handler="diya_dashboard_toggle"/-->
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="GtkScrolledWindow">
|
||||||
|
<property name="hexpand">1</property>
|
||||||
|
<property name="vscrollbar-policy">never</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkListView" id="apps_list">
|
||||||
|
<property name="orientation">horizontal</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</template>
|
||||||
|
</interface>
|
1910
resources/vkb/default.keymap
Normal file
1910
resources/vkb/default.keymap
Normal file
File diff suppressed because it is too large
Load Diff
7
resources/vkb/tpl.keymap
Normal file
7
resources/vkb/tpl.keymap
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
xkb_keymap {
|
||||||
|
xkb_keycodes { include "evdev+aliases(azerty)" };
|
||||||
|
xkb_types { include "complete" };
|
||||||
|
xkb_compat { include "complete" };
|
||||||
|
xkb_symbols { include "pc+fr+inet(evdev)" };
|
||||||
|
xkb_geometry { include "pc(pc105)" };
|
||||||
|
};
|
@ -1,6 +1,7 @@
|
|||||||
#include "background.h"
|
#include "background.h"
|
||||||
|
#include "session-shell.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#define NAMESPACE "background"
|
#define NAMESPACE "diya_shell_background"
|
||||||
|
|
||||||
static void on_background_destroy(GtkWindow *window, GApplication *_data)
|
static void on_background_destroy(GtkWindow *window, GApplication *_data)
|
||||||
{
|
{
|
||||||
@ -12,7 +13,7 @@ static void on_background_destroy(GtkWindow *window, GApplication *_data)
|
|||||||
void diya_session_shell_init_background(DiyaSessionShell * shell)
|
void diya_session_shell_init_background(DiyaSessionShell * shell)
|
||||||
{
|
{
|
||||||
GtkApplication * app;
|
GtkApplication * app;
|
||||||
g_object_get(shell, "application", &app, NULL);
|
g_object_get(shell, DIYA_PROP_SHELL_APPLICATION, &app, NULL);
|
||||||
assert(app);
|
assert(app);
|
||||||
GtkWindow *gtk_window = GTK_WINDOW (gtk_application_window_new (app));
|
GtkWindow *gtk_window = GTK_WINDOW (gtk_application_window_new (app));
|
||||||
assert(gtk_window);
|
assert(gtk_window);
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#ifndef DIYA_SHELL_BACKGROUND_H
|
#ifndef DIYA_SHELL_BACKGROUND_H
|
||||||
#define DIYA_SHELL_BACKGROUND_H
|
#define DIYA_SHELL_BACKGROUND_H
|
||||||
|
|
||||||
#include "session-shell.h"
|
#include "base.h"
|
||||||
|
USE_CLASS(DiyaSessionShell);
|
||||||
|
|
||||||
void diya_session_shell_init_background(DiyaSessionShell * shell);
|
void diya_session_shell_init_background(DiyaSessionShell * shell);
|
||||||
|
|
||||||
|
27
src/base.c
27
src/base.c
@ -3,6 +3,11 @@
|
|||||||
|
|
||||||
G_DEFINE_ABSTRACT_TYPE(DiyaObject, diya_object, G_TYPE_OBJECT)
|
G_DEFINE_ABSTRACT_TYPE(DiyaObject, diya_object, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static void diya_object_finalize(GObject* object)
|
||||||
|
{
|
||||||
|
g_debug("diya_object_finalize: %s", diya_object_to_string(object));
|
||||||
|
G_OBJECT_CLASS (diya_object_parent_class)->finalize(object);
|
||||||
|
}
|
||||||
|
|
||||||
static void diya_object_dispose(GObject* object)
|
static void diya_object_dispose(GObject* object)
|
||||||
{
|
{
|
||||||
@ -15,6 +20,7 @@ static void diya_object_class_init(DiyaObjectClass *class)
|
|||||||
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
class->to_string = NULL;
|
class->to_string = NULL;
|
||||||
gobject_class->dispose = diya_object_dispose;
|
gobject_class->dispose = diya_object_dispose;
|
||||||
|
gobject_class->finalize = diya_object_finalize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void diya_object_init(DiyaObject *self)
|
static void diya_object_init(DiyaObject *self)
|
||||||
@ -22,6 +28,11 @@ static void diya_object_init(DiyaObject *self)
|
|||||||
(void) self;
|
(void) self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Implementation of DiyaShellObject
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
SO_NO_PROP,
|
SO_NO_PROP,
|
||||||
@ -38,6 +49,12 @@ typedef struct _DiyaShellObjectPrivate
|
|||||||
} DiyaShellObjectPrivate;
|
} DiyaShellObjectPrivate;
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE(DiyaShellObject, diya_shell_object, DIYA_TYPE_OBJECT);
|
G_DEFINE_TYPE_WITH_PRIVATE(DiyaShellObject, diya_shell_object, DIYA_TYPE_OBJECT);
|
||||||
|
|
||||||
|
static void diya_shell_object_finalize(GObject* object)
|
||||||
|
{
|
||||||
|
g_debug("diya_shell_object_finalize: %s", diya_object_to_string(object));
|
||||||
|
G_OBJECT_CLASS(diya_shell_object_parent_class)->finalize(object);
|
||||||
|
}
|
||||||
|
|
||||||
static void diya_shell_object_dispose(GObject* object)
|
static void diya_shell_object_dispose(GObject* object)
|
||||||
{
|
{
|
||||||
g_debug("diya_shell_object_dispose: %s", diya_object_to_string(object));
|
g_debug("diya_shell_object_dispose: %s", diya_object_to_string(object));
|
||||||
@ -86,9 +103,10 @@ static void diya_shell_object_class_init(DiyaShellObjectClass *class)
|
|||||||
{
|
{
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
gobject_class->dispose = diya_shell_object_dispose;
|
gobject_class->dispose = diya_shell_object_dispose;
|
||||||
|
gobject_class->finalize = diya_shell_object_finalize;
|
||||||
gobject_class->set_property = diya_shell_object_set_property;
|
gobject_class->set_property = diya_shell_object_set_property;
|
||||||
gobject_class->get_property = diya_shell_object_get_property;
|
gobject_class->get_property = diya_shell_object_get_property;
|
||||||
g_so_prop[SO_SHELL] = g_param_spec_pointer("shell", NULL, "Reference to global shell", G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY); //
|
g_so_prop[SO_SHELL] = g_param_spec_pointer(DIYA_PROP_SHELL, NULL, "Reference to global shell", G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY); //
|
||||||
|
|
||||||
g_object_class_install_properties (gobject_class, SO_N_PROPERTIES, g_so_prop);
|
g_object_class_install_properties (gobject_class, SO_N_PROPERTIES, g_so_prop);
|
||||||
}
|
}
|
||||||
@ -101,3 +119,10 @@ const gchar * diya_object_to_string(gpointer object)
|
|||||||
DiyaObjectClass *class = DIYA_OBJECT_GET_CLASS(self);
|
DiyaObjectClass *class = DIYA_OBJECT_GET_CLASS(self);
|
||||||
return class->to_string ? class->to_string(self) : "";
|
return class->to_string ? class->to_string(self) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gpointer diya_shell_object_get_shell(gpointer object)
|
||||||
|
{
|
||||||
|
DiyaShellObject * self = DIYA_SHELL_OBJECT(object);
|
||||||
|
DiyaShellObjectPrivate* priv = diya_shell_object_get_instance_private(self);
|
||||||
|
return priv->shell;
|
||||||
|
}
|
@ -3,6 +3,11 @@
|
|||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define USE_CLASS(name) typedef struct _##name name
|
||||||
|
#define DIYA_PROP_SHELL "shell"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class object
|
* Base class object
|
||||||
@ -30,5 +35,6 @@ struct _DiyaShellObjectClass
|
|||||||
};
|
};
|
||||||
|
|
||||||
const gchar *diya_object_to_string(gpointer object);
|
const gchar *diya_object_to_string(gpointer object);
|
||||||
|
gpointer diya_shell_object_get_shell(gpointer object);
|
||||||
|
|
||||||
#endif
|
#endif
|
14
src/files-monior.h
Normal file
14
src/files-monior.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef DIYA_FILES_MONITOR_H
|
||||||
|
#define DIYA_FILES_MONITOR_H
|
||||||
|
|
||||||
|
#include "base.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define DIYA_TYPE_FILES_MONITOR (diya_files_monitor_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (DiyaFilesMonitor, diya_files_monitor, DIYA, FILES_MONITOR, DiyaObject)
|
||||||
|
|
||||||
|
DiyaFilesMonitor* diya_files_monitor_new();
|
||||||
|
gboolean diya_files_monitor_watch(DiyaFilesMonitor* monitor, const gchar* file, GCallback callback, gpointer userdata);
|
||||||
|
void diya_files_monitor_unwatch(DiyaFilesMonitor* monitor, const gchar* file);
|
||||||
|
|
||||||
|
#endif
|
91
src/files-monitor.c
Normal file
91
src/files-monitor.c
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#include <glib-unix.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "files-monior.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct _DiyaFilesMonitor
|
||||||
|
{
|
||||||
|
DiyaObject parent;
|
||||||
|
GHashTable *watch_table;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
G_DEFINE_FINAL_TYPE(DiyaFilesMonitor, diya_files_monitor, DIYA_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static void diya_files_monitor_finalize(GObject *object)
|
||||||
|
{
|
||||||
|
DiyaFilesMonitor *self = DIYA_FILES_MONITOR(object);
|
||||||
|
g_debug("diya_files_monitor_finalize: %s", diya_object_to_string(object));
|
||||||
|
g_hash_table_destroy(self->watch_table);
|
||||||
|
G_OBJECT_CLASS(diya_files_monitor_parent_class)->finalize(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_files_monitor_dispose(GObject *object)
|
||||||
|
{
|
||||||
|
// DiyaFilesMonitor *self = DIYA_FILES_MONITOR(object);
|
||||||
|
g_debug("diya_files_monitor_dispose: %s", diya_object_to_string(object));
|
||||||
|
G_OBJECT_CLASS(diya_files_monitor_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_files_monitor_init(DiyaFilesMonitor *self)
|
||||||
|
{
|
||||||
|
self->watch_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar *diya_files_monitor_to_string(DiyaObject *object)
|
||||||
|
{
|
||||||
|
(void) object;
|
||||||
|
return "Diya Files Monitor";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_files_monitor_class_init(DiyaFilesMonitorClass *class)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
|
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
||||||
|
|
||||||
|
gobject_class->finalize = diya_files_monitor_finalize;
|
||||||
|
gobject_class->dispose = diya_files_monitor_dispose;
|
||||||
|
base_class->to_string = diya_files_monitor_to_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
DiyaFilesMonitor* diya_files_monitor_new()
|
||||||
|
{
|
||||||
|
DiyaFilesMonitor* self = DIYA_FILES_MONITOR(g_object_new(DIYA_TYPE_FILES_MONITOR, NULL));
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean diya_files_monitor_watch(DiyaFilesMonitor* self, const gchar* path, GCallback callback, gpointer userdata)
|
||||||
|
{
|
||||||
|
GFileMonitor* fm = NULL;
|
||||||
|
if(!g_hash_table_contains(self->watch_table, path))
|
||||||
|
{
|
||||||
|
GError *err = NULL;
|
||||||
|
GFile* file = g_file_new_for_path(path);
|
||||||
|
fm = g_file_monitor(file, G_FILE_MONITOR_WATCH_MOVES, NULL, &err);
|
||||||
|
g_object_unref(file);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
g_warning("Unable to watch file %s: %s", path, err->message);
|
||||||
|
g_error_free(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
g_info("DiyaFilesMonitor: watch new file: %s", path);
|
||||||
|
g_hash_table_insert(self->watch_table, (gpointer)g_strdup(path), fm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_info("File %s is already watched, register callback handle to the existing watcher", path);
|
||||||
|
fm = g_hash_table_lookup(self->watch_table, path);
|
||||||
|
}
|
||||||
|
g_signal_connect(G_OBJECT(fm), "changed", callback, userdata);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_files_monitor_unwatch(DiyaFilesMonitor* self, const gchar* path)
|
||||||
|
{
|
||||||
|
if(!g_hash_table_contains(self->watch_table, path))
|
||||||
|
{
|
||||||
|
g_hash_table_remove(self->watch_table, (gconstpointer)path);
|
||||||
|
}
|
||||||
|
}
|
176
src/foreign.c
176
src/foreign.c
@ -2,6 +2,8 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "wlr-foreign-toplevel-management-unstable-v1.h"
|
#include "wlr-foreign-toplevel-management-unstable-v1.h"
|
||||||
#include "foreign.h"
|
#include "foreign.h"
|
||||||
|
#include "wayland.h"
|
||||||
|
#include "session-shell.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @DiyaForeignWindow Object definition
|
* @DiyaForeignWindow Object definition
|
||||||
@ -26,22 +28,36 @@ struct _DiyaForeignWindow
|
|||||||
gchar* title;
|
gchar* title;
|
||||||
enum diya_win_state state;
|
enum diya_win_state state;
|
||||||
DiyaForeignWindow * parent_win;
|
DiyaForeignWindow * parent_win;
|
||||||
gchar string[128];
|
gchar* string;
|
||||||
};
|
};
|
||||||
G_DEFINE_FINAL_TYPE(DiyaForeignWindow, diya_foreign_window, DIYA_TYPE_SHELL_OBJECT)
|
G_DEFINE_FINAL_TYPE(DiyaForeignWindow, diya_foreign_window, DIYA_TYPE_SHELL_OBJECT)
|
||||||
|
|
||||||
|
static void diya_foreign_window_finalize(GObject* object)
|
||||||
|
{
|
||||||
|
DiyaForeignWindow * self = DIYA_FOREIGN_WINDOW(object);
|
||||||
|
g_debug("diya_foreign_window_finalize: %s", diya_object_to_string(self));
|
||||||
|
if(self->appid)
|
||||||
|
{
|
||||||
|
g_free(self->appid);
|
||||||
|
self->appid = NULL;
|
||||||
|
}
|
||||||
|
if(self->title)
|
||||||
|
{
|
||||||
|
g_free(self->title);
|
||||||
|
self->title = NULL;
|
||||||
|
}
|
||||||
|
if(self->string)
|
||||||
|
{
|
||||||
|
g_free(self->string);
|
||||||
|
self->string = NULL;
|
||||||
|
}
|
||||||
|
G_OBJECT_CLASS(diya_foreign_window_parent_class)->finalize(object);
|
||||||
|
}
|
||||||
|
|
||||||
static void diya_foreign_window_dispose(GObject* object)
|
static void diya_foreign_window_dispose(GObject* object)
|
||||||
{
|
{
|
||||||
DiyaForeignWindow * self = DIYA_FOREIGN_WINDOW(object);
|
DiyaForeignWindow * self = DIYA_FOREIGN_WINDOW(object);
|
||||||
g_debug("diya_foreign_window_dispose: %s", diya_object_to_string(self));
|
g_debug("diya_foreign_window_dispose: %s", diya_object_to_string(self));
|
||||||
if(self->appid)
|
|
||||||
{
|
|
||||||
g_free(self->appid);
|
|
||||||
}
|
|
||||||
if(self->title)
|
|
||||||
{
|
|
||||||
g_free(self->title);
|
|
||||||
}
|
|
||||||
G_OBJECT_CLASS(diya_foreign_window_parent_class)->dispose(object);
|
G_OBJECT_CLASS(diya_foreign_window_parent_class)->dispose(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,13 +130,18 @@ static void diya_foreign_window_init(DiyaForeignWindow *self)
|
|||||||
//self->shell = NULL;
|
//self->shell = NULL;
|
||||||
self->state = DIYA_WIN_STATE_NONE;
|
self->state = DIYA_WIN_STATE_NONE;
|
||||||
self->title = NULL;
|
self->title = NULL;
|
||||||
memset(self->string, 0, sizeof(self->string));
|
self->string = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const gchar* diya_foreign_window_to_string(DiyaObject* object)
|
static const gchar* diya_foreign_window_to_string(DiyaObject* object)
|
||||||
{
|
{
|
||||||
DiyaForeignWindow* self = DIYA_FOREIGN_WINDOW(object);
|
DiyaForeignWindow* self = DIYA_FOREIGN_WINDOW(object);
|
||||||
g_snprintf(self->string, sizeof(self->string), "Window 0x%" PRIXPTR ": %s (%s)", (uintptr_t) self->handle, self->appid?self->appid:"", self->title?self->title:"");
|
if(!self->string)
|
||||||
|
{
|
||||||
|
self->string = (char*) malloc(128);
|
||||||
|
g_snprintf(self->string, 128, "Window 0x%" PRIXPTR ": %s (%s)", (uintptr_t) self->handle, self->appid?self->appid:"", self->title?self->title:"");
|
||||||
|
}
|
||||||
|
|
||||||
return self->string;
|
return self->string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,20 +151,19 @@ static void diya_foreign_window_class_init(DiyaForeignWindowClass *class)
|
|||||||
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
||||||
|
|
||||||
gobject_class->dispose = diya_foreign_window_dispose;
|
gobject_class->dispose = diya_foreign_window_dispose;
|
||||||
|
gobject_class->finalize = diya_foreign_window_finalize;
|
||||||
gobject_class->set_property = diya_foreign_window_set_property;
|
gobject_class->set_property = diya_foreign_window_set_property;
|
||||||
gobject_class->get_property = diya_foreign_window_get_property;
|
gobject_class->get_property = diya_foreign_window_get_property;
|
||||||
base_class->to_string = diya_foreign_window_to_string;
|
base_class->to_string = diya_foreign_window_to_string;
|
||||||
|
|
||||||
win_properties[WIN_APP_ID] = g_param_spec_string("appid", NULL, "Window application id", "", G_PARAM_READWRITE);
|
win_properties[WIN_APP_ID] = g_param_spec_string(DIYA_PROP_FOREIGN_WINDOW_APPID, NULL, "Window application id", "", G_PARAM_READWRITE);
|
||||||
win_properties[WIN_TITLE] = g_param_spec_string("title", NULL, "Window title","", G_PARAM_READWRITE );
|
win_properties[WIN_TITLE] = g_param_spec_string(DIYA_PROP_FOREIGN_WINDOW_TITLE, NULL, "Window title","", G_PARAM_READWRITE );
|
||||||
win_properties[WIN_HANDLE] = g_param_spec_pointer("handle", NULL, "Foreign window handle", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY );
|
win_properties[WIN_HANDLE] = g_param_spec_pointer(DIYA_PROP_FOREIGN_WINDOW_HANDLE, NULL, "Foreign window handle", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY );
|
||||||
win_properties[WIN_STATE] = g_param_spec_uint("state", NULL, "Window state",0, UINT_MAX , DIYA_WIN_STATE_NONE,G_PARAM_READWRITE);
|
win_properties[WIN_STATE] = g_param_spec_uint(DIYA_PROP_FOREIGN_WINDOW_STATE, NULL, "Window state",0, UINT_MAX , DIYA_WIN_STATE_NONE,G_PARAM_READWRITE);
|
||||||
win_properties[WIN_PARENT] = g_param_spec_pointer("parent", NULL, "Window parent", G_PARAM_READWRITE);
|
win_properties[WIN_PARENT] = g_param_spec_pointer(DIYA_PROP_FOREIGN_WINDOW_PARENT, NULL, "Window parent", G_PARAM_READWRITE);
|
||||||
g_object_class_install_properties (gobject_class, N_PROPERTIES, win_properties);
|
g_object_class_install_properties (gobject_class, N_PROPERTIES, win_properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct zwlr_foreign_toplevel_manager_v1 *g_toplevel_manager;
|
|
||||||
|
|
||||||
static void toplevel_handle_output_leave(void *data,
|
static void toplevel_handle_output_leave(void *data,
|
||||||
struct zwlr_foreign_toplevel_handle_v1 *handle,
|
struct zwlr_foreign_toplevel_handle_v1 *handle,
|
||||||
struct wl_output *output)
|
struct wl_output *output)
|
||||||
@ -173,6 +193,7 @@ static void toplevel_handle_app_id(void *data,
|
|||||||
assert(win);
|
assert(win);
|
||||||
g_object_set(win, "appid", app_id, NULL);
|
g_object_set(win, "appid", app_id, NULL);
|
||||||
g_debug("New appid for: %s", diya_object_to_string(win));
|
g_debug("New appid for: %s", diya_object_to_string(win));
|
||||||
|
g_signal_emit_by_name(shell, DIYA_SIGNAL_FOREIGN_WINDOW_ADDED, (void *)win);
|
||||||
}
|
}
|
||||||
static void toplevel_handle_output_enter(void *data,
|
static void toplevel_handle_output_enter(void *data,
|
||||||
struct zwlr_foreign_toplevel_handle_v1 *handle,
|
struct zwlr_foreign_toplevel_handle_v1 *handle,
|
||||||
@ -207,7 +228,10 @@ static void toplevel_handle_state(void *data,
|
|||||||
wstate |= DIYA_WIN_STATE_FOCUS;
|
wstate |= DIYA_WIN_STATE_FOCUS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
g_debug("toplevel_handle_state %s: (%.04x) active: %d, full screen %d, maximize %d, minimize %d", diya_object_to_string(win), wstate, wstate & DIYA_WIN_STATE_FOCUS,
|
||||||
|
wstate & DIYA_WIN_STATE_FULLSCREEN, wstate & DIYA_WIN_STATE_MAXIMIZE, wstate & DIYA_WIN_STATE_MINIMIZE);
|
||||||
g_object_set(win, "state", wstate, NULL);
|
g_object_set(win, "state", wstate, NULL);
|
||||||
|
g_signal_emit_by_name(shell, DIYA_SIGNAL_FOREIGN_WINDOW_STATE_CHANGED, (void *)win, (guint)wstate);
|
||||||
}
|
}
|
||||||
static void toplevel_handle_done(void *data,
|
static void toplevel_handle_done(void *data,
|
||||||
struct zwlr_foreign_toplevel_handle_v1 *handle)
|
struct zwlr_foreign_toplevel_handle_v1 *handle)
|
||||||
@ -216,7 +240,8 @@ static void toplevel_handle_done(void *data,
|
|||||||
assert(shell);
|
assert(shell);
|
||||||
DiyaForeignWindow *win = diya_session_shell_get_window(shell, handle);
|
DiyaForeignWindow *win = diya_session_shell_get_window(shell, handle);
|
||||||
assert(win);
|
assert(win);
|
||||||
g_signal_emit_by_name(shell, "foreign-window-changed", (void *)win);
|
g_debug("toplevel_handle_done: finish");
|
||||||
|
g_signal_emit_by_name(shell, DIYA_SIGNAL_FOREIGN_WINDOW_CHANGED, (void *)win);
|
||||||
}
|
}
|
||||||
static void toplevel_handle_closed(void *data,
|
static void toplevel_handle_closed(void *data,
|
||||||
struct zwlr_foreign_toplevel_handle_v1 *handle)
|
struct zwlr_foreign_toplevel_handle_v1 *handle)
|
||||||
@ -225,7 +250,7 @@ static void toplevel_handle_closed(void *data,
|
|||||||
assert(shell);
|
assert(shell);
|
||||||
DiyaForeignWindow *win = diya_session_shell_get_window(shell, handle);
|
DiyaForeignWindow *win = diya_session_shell_get_window(shell, handle);
|
||||||
assert(win);
|
assert(win);
|
||||||
g_signal_emit_by_name(shell, "foreign-window-removed", (void *)win);
|
g_signal_emit_by_name(shell, DIYA_SIGNAL_FOREIGN_WINDOW_REMOVED, (void *)win);
|
||||||
diya_session_shell_remove_window(shell, win);
|
diya_session_shell_remove_window(shell, win);
|
||||||
zwlr_foreign_toplevel_handle_v1_destroy(handle);
|
zwlr_foreign_toplevel_handle_v1_destroy(handle);
|
||||||
}
|
}
|
||||||
@ -302,9 +327,114 @@ static const struct zwlr_foreign_toplevel_manager_v1_listener g_toplevel_manager
|
|||||||
.finished = toplevel_manager_handle_finished,
|
.finished = toplevel_manager_handle_finished,
|
||||||
};
|
};
|
||||||
|
|
||||||
void diya_session_shell_foreign_toplevel_register(struct wl_registry *registry, uint32_t name, DiyaShell *shell)
|
void diya_session_shell_foreign_toplevel_register(gpointer mngr, DiyaShell *shell)
|
||||||
{
|
{
|
||||||
DiyaSessionShell* session_shell = DIYA_SESSION_SHELL(shell);
|
DiyaSessionShell* session_shell = DIYA_SESSION_SHELL(shell);
|
||||||
g_toplevel_manager = wl_registry_bind(registry, name, &zwlr_foreign_toplevel_manager_v1_interface, 3);
|
zwlr_foreign_toplevel_manager_v1_add_listener(mngr, &g_toplevel_manager_impl, (void *)session_shell);
|
||||||
zwlr_foreign_toplevel_manager_v1_add_listener(g_toplevel_manager, &g_toplevel_manager_impl, (void *)session_shell);
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DiyaShell* diya_foreign_window_get_shell(DiyaForeignWindow* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
gpointer ptr;
|
||||||
|
|
||||||
|
g_object_get(self, DIYA_PROP_SHELL, &ptr, NULL);
|
||||||
|
DiyaShell* shell = DIYA_SHELL(ptr);
|
||||||
|
assert(shell);
|
||||||
|
return shell;
|
||||||
|
}
|
||||||
|
void diya_foreign_window_set_state(DiyaForeignWindow* self, enum diya_win_state state, bool value)
|
||||||
|
{
|
||||||
|
DiyaShell* shell = diya_foreign_window_get_shell(self);
|
||||||
|
DiyaWayland* wl = diya_shell_get_wayland(shell);
|
||||||
|
assert(wl);
|
||||||
|
if(state & DIYA_WIN_STATE_MINIMIZE)
|
||||||
|
{
|
||||||
|
if(value)
|
||||||
|
{
|
||||||
|
zwlr_foreign_toplevel_handle_v1_set_minimized(self->handle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
zwlr_foreign_toplevel_handle_v1_unset_minimized(self->handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(state & DIYA_WIN_STATE_MAXIMIZE)
|
||||||
|
{
|
||||||
|
if(value)
|
||||||
|
{
|
||||||
|
zwlr_foreign_toplevel_handle_v1_set_maximized(self->handle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
zwlr_foreign_toplevel_handle_v1_unset_maximized(self->handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(state & DIYA_WIN_STATE_FULLSCREEN)
|
||||||
|
{
|
||||||
|
struct wl_output* output = diya_wayland_get_output(wl, 0);
|
||||||
|
if(value)
|
||||||
|
{
|
||||||
|
zwlr_foreign_toplevel_handle_v1_set_fullscreen(self->handle, output);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
zwlr_foreign_toplevel_handle_v1_unset_fullscreen(self->handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(state & DIYA_WIN_STATE_FOCUS)
|
||||||
|
{
|
||||||
|
if(value)
|
||||||
|
{
|
||||||
|
struct wl_seat* seat = diya_wayland_get_seat(wl);
|
||||||
|
zwlr_foreign_toplevel_handle_v1_activate(self->handle, seat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool diya_foreign_window_is_toplevel(DiyaForeignWindow* self)
|
||||||
|
{
|
||||||
|
return self->parent_win == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint app_info_str_cmp(GAppInfo* info, const char* id)
|
||||||
|
{
|
||||||
|
return g_strcmp0(g_app_info_get_executable(info), id);
|
||||||
|
}
|
||||||
|
|
||||||
|
GAppInfo* diya_foreign_window_get_app_info(DiyaForeignWindow* self)
|
||||||
|
{
|
||||||
|
if(! self->appid)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
GList* apps = g_app_info_get_all();
|
||||||
|
GList* found = g_list_find_custom(apps, self->appid, (GCompareFunc)app_info_str_cmp);
|
||||||
|
GAppInfo* info = NULL;
|
||||||
|
if(found && found->data)
|
||||||
|
{
|
||||||
|
assert(G_IS_APP_INFO(found->data));
|
||||||
|
info = g_object_ref(found->data);
|
||||||
|
}
|
||||||
|
g_list_free_full(apps, g_object_unref);
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum diya_win_state diya_foreign_window_get_state(DiyaForeignWindow* window)
|
||||||
|
{
|
||||||
|
return window->state;
|
||||||
|
}
|
||||||
|
|
||||||
|
DiyaForeignWindow* diya_foreign_window_get_top_level(DiyaForeignWindow* self)
|
||||||
|
{
|
||||||
|
DiyaForeignWindow* win = self;
|
||||||
|
while(win->parent_win)
|
||||||
|
{
|
||||||
|
win = win->parent_win;
|
||||||
|
}
|
||||||
|
return win;
|
||||||
}
|
}
|
@ -1,6 +1,16 @@
|
|||||||
#ifndef DIYA_SHELL_FOREIGN_H
|
#ifndef DIYA_SHELL_FOREIGN_H
|
||||||
#define DIYA_SHELL_FOREIGN_H
|
#define DIYA_SHELL_FOREIGN_H
|
||||||
#include "session-shell.h"
|
#include "base.h"
|
||||||
|
|
||||||
|
#define DIYA_TYPE_FOREIGN_WINDOW (diya_foreign_window_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (DiyaForeignWindow, diya_foreign_window, DIYA, FOREIGN_WINDOW, DiyaShellObject)
|
||||||
|
|
||||||
|
|
||||||
|
#define DIYA_PROP_FOREIGN_WINDOW_APPID "appid"
|
||||||
|
#define DIYA_PROP_FOREIGN_WINDOW_TITLE "title"
|
||||||
|
#define DIYA_PROP_FOREIGN_WINDOW_HANDLE "handle"
|
||||||
|
#define DIYA_PROP_FOREIGN_WINDOW_STATE "state"
|
||||||
|
#define DIYA_PROP_FOREIGN_WINDOW_PARENT "parent"
|
||||||
|
|
||||||
enum diya_win_state
|
enum diya_win_state
|
||||||
{
|
{
|
||||||
@ -11,6 +21,16 @@ enum diya_win_state
|
|||||||
DIYA_WIN_STATE_FOCUS = 1 << 3,
|
DIYA_WIN_STATE_FOCUS = 1 << 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
void diya_session_shell_foreign_toplevel_register(struct wl_registry *registry, uint32_t name, DiyaShell * shell);
|
USE_CLASS(DiyaShell);
|
||||||
|
USE_CLASS(GAppInfo);
|
||||||
|
|
||||||
|
void diya_session_shell_foreign_toplevel_register(gpointer mngr, DiyaShell * shell);
|
||||||
|
|
||||||
|
DiyaShell* diya_foreign_window_get_shell(DiyaForeignWindow* window);
|
||||||
|
|
||||||
|
void diya_foreign_window_set_state(DiyaForeignWindow* window, enum diya_win_state state, bool value);
|
||||||
|
enum diya_win_state diya_foreign_window_get_state(DiyaForeignWindow* window);
|
||||||
|
bool diya_foreign_window_is_toplevel(DiyaForeignWindow* window);
|
||||||
|
DiyaForeignWindow* diya_foreign_window_get_top_level(DiyaForeignWindow* window);
|
||||||
|
GAppInfo* diya_foreign_window_get_app_info(DiyaForeignWindow* window);
|
||||||
#endif
|
#endif
|
135
src/idle.c
Normal file
135
src/idle.c
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#include "idle.h"
|
||||||
|
#include "wayland.h"
|
||||||
|
#include "ext-idle-notify-v1.h"
|
||||||
|
#include "shell.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct _DiyaIdleNotification
|
||||||
|
{
|
||||||
|
DiyaShellObject parent;
|
||||||
|
struct ext_idle_notification_v1* notification;
|
||||||
|
guint timeout;
|
||||||
|
gchar* str;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_FINAL_TYPE(DiyaIdleNotification, diya_idle_notification, DIYA_TYPE_SHELL_OBJECT)
|
||||||
|
|
||||||
|
static void diya_idle_notification_finalize(GObject* object)
|
||||||
|
{
|
||||||
|
(void) object;
|
||||||
|
DiyaIdleNotification * self = DIYA_IDLE_NOTIFICATION(object);
|
||||||
|
if(self->notification)
|
||||||
|
{
|
||||||
|
ext_idle_notification_v1_destroy(self->notification);
|
||||||
|
self->notification = NULL;
|
||||||
|
}
|
||||||
|
g_debug("diya_idle_notification_finalize: %s", diya_object_to_string(object));
|
||||||
|
if(self->str)
|
||||||
|
{
|
||||||
|
g_free(self->str);
|
||||||
|
self->str = NULL;
|
||||||
|
}
|
||||||
|
G_OBJECT_CLASS(diya_idle_notification_parent_class)->finalize(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_idle_notification_dispose(GObject* object)
|
||||||
|
{
|
||||||
|
(void) object;
|
||||||
|
// DiyaIdleNotification * self = DIYA_IDLE_NOTIFICATION(object);
|
||||||
|
g_debug("diya_idle_notification_dispose: %s", diya_object_to_string(object));
|
||||||
|
G_OBJECT_CLASS(diya_idle_notification_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_idle_notification_init(DiyaIdleNotification * self)
|
||||||
|
{
|
||||||
|
self->notification = NULL;
|
||||||
|
self->str = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar* diya_idle_notification_to_string(DiyaObject* object)
|
||||||
|
{
|
||||||
|
DiyaIdleNotification * self = DIYA_IDLE_NOTIFICATION(object);
|
||||||
|
if(!self->str)
|
||||||
|
{
|
||||||
|
self->str = (gchar*) malloc(64);
|
||||||
|
g_snprintf(self->str, 64, "DiyaIdleNotification for timeout: %d (ms)", self->timeout);
|
||||||
|
}
|
||||||
|
return self->str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_idle_notification_class_init(DiyaIdleNotificationClass *class)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
|
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
||||||
|
|
||||||
|
gobject_class->dispose = diya_idle_notification_dispose;
|
||||||
|
gobject_class->finalize = diya_idle_notification_finalize;
|
||||||
|
base_class->to_string = diya_idle_notification_to_string;
|
||||||
|
|
||||||
|
g_signal_new(DIYA_SIGNAL_IDLE_NOTIF_IDLE,
|
||||||
|
DIYA_TYPE_IDLE_NOTIFICATION,
|
||||||
|
G_SIGNAL_DETAILED |
|
||||||
|
G_SIGNAL_ACTION |
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
0);
|
||||||
|
|
||||||
|
g_signal_new(DIYA_SIGNAL_IDLE_NOTIF_RESUME,
|
||||||
|
DIYA_TYPE_IDLE_NOTIFICATION,
|
||||||
|
G_SIGNAL_DETAILED |
|
||||||
|
G_SIGNAL_ACTION |
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_idle(void *data, struct ext_idle_notification_v1 *notification)
|
||||||
|
{
|
||||||
|
(void) notification;
|
||||||
|
DiyaIdleNotification* self = data;
|
||||||
|
g_signal_emit_by_name(self, DIYA_SIGNAL_IDLE_NOTIF_IDLE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_resume(void *data, struct ext_idle_notification_v1 *notification)
|
||||||
|
{
|
||||||
|
(void) notification;
|
||||||
|
DiyaIdleNotification* self = data;
|
||||||
|
g_signal_emit_by_name(self, DIYA_SIGNAL_IDLE_NOTIF_RESUME);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct ext_idle_notification_v1_listener g_idle_listener_impl =
|
||||||
|
{
|
||||||
|
.idled = diya_idle,
|
||||||
|
.resumed = diya_resume
|
||||||
|
};
|
||||||
|
|
||||||
|
DiyaIdleNotification* diya_shell_get_idle_notification(DiyaShell* shell, guint timeout_ms)
|
||||||
|
{
|
||||||
|
DiyaWayland *wayland = diya_shell_get_wayland(shell);
|
||||||
|
struct ext_idle_notifier_v1* mngr = diya_wayland_get_idle_mngr(wayland);
|
||||||
|
if(!mngr)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
DiyaIdleNotification* self = g_object_new(DIYA_TYPE_IDLE_NOTIFICATION, "shell", shell, NULL);
|
||||||
|
struct wl_seat *seat = diya_wayland_get_seat(wayland);
|
||||||
|
self->timeout = timeout_ms;
|
||||||
|
self->notification = ext_idle_notifier_v1_get_idle_notification(mngr, timeout_ms, seat);
|
||||||
|
ext_idle_notification_v1_add_listener(self->notification, &g_idle_listener_impl, self);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
guint diya_idle_notification_get_timeout(DiyaIdleNotification* self)
|
||||||
|
{
|
||||||
|
return self->timeout;
|
||||||
|
}
|
17
src/idle.h
Normal file
17
src/idle.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef DIYAC_IDLE_H
|
||||||
|
#define DIYAC_IDLE_H
|
||||||
|
|
||||||
|
#include "base.h"
|
||||||
|
|
||||||
|
#define DIYA_SIGNAL_IDLE_NOTIF_IDLE "idle"
|
||||||
|
#define DIYA_SIGNAL_IDLE_NOTIF_RESUME "resume"
|
||||||
|
|
||||||
|
#define DIYA_TYPE_IDLE_NOTIFICATION (diya_idle_notification_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (DiyaIdleNotification, diya_idle_notification, DIYA, IDLE_NOTIFICATION, DiyaShellObject)
|
||||||
|
|
||||||
|
USE_CLASS(DiyaShell);
|
||||||
|
|
||||||
|
void diya_idle_manager_register(gpointer mngr, DiyaShell *shell);
|
||||||
|
DiyaIdleNotification* diya_shell_get_idle_notification(DiyaShell* shell, guint timeout_ms);
|
||||||
|
guint diya_idle_notification_get_timeout(DiyaIdleNotification* self);
|
||||||
|
#endif /* DIYAC_IDLE_H */
|
243
src/input.c
Normal file
243
src/input.c
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
#include "input.h"
|
||||||
|
|
||||||
|
#include <wayland-client-protocol.h>
|
||||||
|
#include <gdk/wayland/gdkwayland.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
#include "wlr-foreign-toplevel-management-unstable-v1.h"
|
||||||
|
#include "virtual-keyboard-unstable-v1.h"
|
||||||
|
#include "wayland.h"
|
||||||
|
#include "shell.h"
|
||||||
|
|
||||||
|
struct _DiyaInput
|
||||||
|
{
|
||||||
|
DiyaShellObject parent;
|
||||||
|
gchar *name;
|
||||||
|
struct wl_keyboard *keyboard;
|
||||||
|
struct wl_seat *seat;
|
||||||
|
struct xkb_state *xkb_state;
|
||||||
|
struct xkb_context *xkb_context;
|
||||||
|
struct xkb_keymap *xkb_keymap;
|
||||||
|
};
|
||||||
|
G_DEFINE_FINAL_TYPE(DiyaInput, diya_input, DIYA_TYPE_SHELL_OBJECT)
|
||||||
|
|
||||||
|
static void diya_input_finalize(GObject *object)
|
||||||
|
{
|
||||||
|
g_debug("diya_input_finalize: %s", diya_object_to_string(object));
|
||||||
|
DiyaInput *self = DIYA_INPUT(object);
|
||||||
|
if (self->name)
|
||||||
|
{
|
||||||
|
g_free(self->name);
|
||||||
|
self->name = NULL;
|
||||||
|
}
|
||||||
|
if (self->keyboard)
|
||||||
|
{
|
||||||
|
wl_keyboard_release(self->keyboard);
|
||||||
|
self->keyboard = NULL;
|
||||||
|
}
|
||||||
|
G_OBJECT_CLASS(diya_input_parent_class)->finalize(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_input_dispose(GObject *object)
|
||||||
|
{
|
||||||
|
g_debug("diya_input_dispose: %s", diya_object_to_string(object));
|
||||||
|
DiyaInput *self = DIYA_INPUT(object);
|
||||||
|
if (self->xkb_keymap)
|
||||||
|
{
|
||||||
|
xkb_keymap_unref(self->xkb_keymap);
|
||||||
|
self->xkb_keymap = NULL;
|
||||||
|
}
|
||||||
|
if (self->xkb_state)
|
||||||
|
{
|
||||||
|
xkb_state_unref(self->xkb_state);
|
||||||
|
self->xkb_state = NULL;
|
||||||
|
}
|
||||||
|
if (self->xkb_context)
|
||||||
|
{
|
||||||
|
xkb_context_unref(self->xkb_context);
|
||||||
|
self->xkb_context = NULL;
|
||||||
|
}
|
||||||
|
G_OBJECT_CLASS(diya_input_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_input_init(DiyaInput *self)
|
||||||
|
{
|
||||||
|
self->name = NULL;
|
||||||
|
self->keyboard = NULL;
|
||||||
|
self->xkb_state = NULL;
|
||||||
|
self->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
|
self->xkb_keymap = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar *diya_input_to_string(DiyaObject *object)
|
||||||
|
{
|
||||||
|
DiyaInput *self = DIYA_INPUT(object);
|
||||||
|
if (self->name)
|
||||||
|
{
|
||||||
|
return self->name;
|
||||||
|
}
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_input_class_init(DiyaInputClass *class)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
|
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
||||||
|
|
||||||
|
gobject_class->dispose = diya_input_dispose;
|
||||||
|
gobject_class->finalize = diya_input_finalize;
|
||||||
|
// gobject_class->set_property = diya_input_set_property;
|
||||||
|
// gobject_class->get_property = diya_input_get_property;
|
||||||
|
base_class->to_string = diya_input_to_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wl_keyboard_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int32_t fd, uint32_t size)
|
||||||
|
{
|
||||||
|
(void)keyboard;
|
||||||
|
DiyaInput *self = data;
|
||||||
|
assert(format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1);
|
||||||
|
char *map_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
|
||||||
|
assert(map_shm != MAP_FAILED);
|
||||||
|
struct xkb_keymap *xkb_keymap = xkb_keymap_new_from_string(self->xkb_context, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
munmap(map_shm, size);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
struct xkb_state *xkb_state = xkb_state_new(xkb_keymap);
|
||||||
|
xkb_keymap_unref(self->xkb_keymap);
|
||||||
|
xkb_state_unref(self->xkb_state);
|
||||||
|
self->xkb_keymap = xkb_keymap;
|
||||||
|
self->xkb_state = xkb_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wl_keyboard_enter(void *data, struct wl_keyboard *keyboard,
|
||||||
|
uint32_t serial, struct wl_surface *surface,
|
||||||
|
struct wl_array *keys)
|
||||||
|
{
|
||||||
|
(void)keyboard;
|
||||||
|
(void)serial;
|
||||||
|
(void)surface;
|
||||||
|
DiyaInput *self = data;
|
||||||
|
|
||||||
|
GList* keys_list = NULL;
|
||||||
|
|
||||||
|
uint32_t *key;
|
||||||
|
wl_array_for_each(key, keys)
|
||||||
|
{
|
||||||
|
keys_list = g_list_append(keys_list, (gpointer) key);
|
||||||
|
}
|
||||||
|
g_signal_emit_by_name(diya_shell_object_get_shell(self), DIYA_SIGNAL_SHELL_KEYBOARD_ENTER, self->xkb_keymap, self->xkb_state, (void*) keys_list);
|
||||||
|
g_list_free(keys_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wl_keyboard_key(void *data, struct wl_keyboard *keyboard,
|
||||||
|
uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
|
||||||
|
{
|
||||||
|
(void)keyboard;
|
||||||
|
(void)serial;
|
||||||
|
(void)time;
|
||||||
|
DiyaInput *self = data;
|
||||||
|
if(state == WL_KEYBOARD_KEY_STATE_PRESSED)
|
||||||
|
{
|
||||||
|
g_signal_emit_by_name(diya_shell_object_get_shell(self), DIYA_SIGNAL_SHELL_KEY_PRESSED, self->xkb_keymap, self->xkb_state, key, time);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_signal_emit_by_name(diya_shell_object_get_shell(self), DIYA_SIGNAL_SHELL_KEY_RELEASED, self->xkb_keymap, self->xkb_state, key, time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wl_keyboard_leave(void *data, struct wl_keyboard *keyboard,
|
||||||
|
uint32_t serial, struct wl_surface *surface)
|
||||||
|
{
|
||||||
|
(void)keyboard;
|
||||||
|
(void)serial;
|
||||||
|
(void)surface;
|
||||||
|
DiyaInput *self = data;
|
||||||
|
g_signal_emit_by_name(diya_shell_object_get_shell(self), DIYA_SIGNAL_SHELL_KEYBOARD_LEAVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wl_keyboard_modifiers(void *data, struct wl_keyboard *keyboard,
|
||||||
|
uint32_t serial, uint32_t mods_depressed,
|
||||||
|
uint32_t mods_latched, uint32_t mods_locked,
|
||||||
|
uint32_t group)
|
||||||
|
{
|
||||||
|
(void)keyboard;
|
||||||
|
(void)serial;
|
||||||
|
DiyaInput *self = data;
|
||||||
|
xkb_state_update_mask(self->xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
|
||||||
|
g_signal_emit_by_name(diya_shell_object_get_shell(self), DIYA_SIGNAL_SHELL_KEYBOARD_MODIFIER_CHANGED, self->xkb_keymap, (void*) self->xkb_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wl_keyboard_repeat_info(void *data, struct wl_keyboard *keyboard, int32_t rate, int32_t delay)
|
||||||
|
{
|
||||||
|
(void)data;
|
||||||
|
(void)keyboard;
|
||||||
|
(void)rate;
|
||||||
|
(void)delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_keyboard_listener wl_keyboard_listener = {
|
||||||
|
.keymap = wl_keyboard_keymap,
|
||||||
|
.enter = wl_keyboard_enter,
|
||||||
|
.leave = wl_keyboard_leave,
|
||||||
|
.key = wl_keyboard_key,
|
||||||
|
.modifiers = wl_keyboard_modifiers,
|
||||||
|
.repeat_info = wl_keyboard_repeat_info,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void wl_seat_capabilities(void *data, struct wl_seat *seat, uint32_t capabilities)
|
||||||
|
{
|
||||||
|
DiyaInput *self = data;
|
||||||
|
bool have_keyboard = capabilities & WL_SEAT_CAPABILITY_KEYBOARD;
|
||||||
|
|
||||||
|
if (have_keyboard && self->keyboard == NULL)
|
||||||
|
{
|
||||||
|
self->keyboard = wl_seat_get_keyboard(seat);
|
||||||
|
wl_keyboard_add_listener(self->keyboard, &wl_keyboard_listener, self);
|
||||||
|
}
|
||||||
|
else if (!have_keyboard && self->keyboard != NULL)
|
||||||
|
{
|
||||||
|
wl_keyboard_release(self->keyboard);
|
||||||
|
self->keyboard = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wl_seat_name(void *data, struct wl_seat *seat, const char *name)
|
||||||
|
{
|
||||||
|
(void)seat;
|
||||||
|
DiyaInput *self = data;
|
||||||
|
if (self->name)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_info("Attach to seat: %s", name);
|
||||||
|
self->name = g_strdup(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_seat_listener wl_seat_listener = {
|
||||||
|
.capabilities = wl_seat_capabilities,
|
||||||
|
.name = wl_seat_name,
|
||||||
|
};
|
||||||
|
|
||||||
|
DiyaInput *diya_input_new(DiyaShell *shell)
|
||||||
|
{
|
||||||
|
assert(shell);
|
||||||
|
DiyaInput *self = g_object_new(DIYA_TYPE_INPUT, "shell", shell, NULL);
|
||||||
|
DiyaWayland *wayland = diya_shell_get_wayland(shell);
|
||||||
|
assert(wayland);
|
||||||
|
struct wl_seat *seat = diya_wayland_get_seat(wayland);
|
||||||
|
assert(seat);
|
||||||
|
wl_seat_add_listener(seat, &wl_seat_listener, self);
|
||||||
|
return self;
|
||||||
|
}
|
12
src/input.h
Normal file
12
src/input.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef DIYA_INPUT_H
|
||||||
|
#define DIYA_INPUT_H
|
||||||
|
|
||||||
|
#include "base.h"
|
||||||
|
USE_CLASS(DiyaShell);
|
||||||
|
|
||||||
|
#define DIYA_TYPE_INPUT (diya_input_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (DiyaInput, diya_input, DIYA, INPUT, DiyaShellObject)
|
||||||
|
|
||||||
|
|
||||||
|
DiyaInput* diya_input_new(DiyaShell* shell);
|
||||||
|
#endif
|
222
src/launcher.c
222
src/launcher.c
@ -1,95 +1,165 @@
|
|||||||
#include "launcher.h"
|
#include <wayland-client-protocol.h>
|
||||||
#include "foreign.h"
|
#include <gdk/wayland/gdkwayland.h>
|
||||||
#include "session-lock.h"
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include "launcher.h"
|
||||||
|
#include "widgets/dashboard-widget.h"
|
||||||
|
#include "widgets/taskbar-widget.h"
|
||||||
|
#include "foreign.h"
|
||||||
|
#include "wayland.h"
|
||||||
|
|
||||||
#define NAMESPACE "launcher"
|
struct _DiyaLauncher
|
||||||
|
|
||||||
static void on_launcher_destroy(GtkWindow *window, GApplication *_data)
|
|
||||||
{
|
{
|
||||||
(void) window;
|
DiyaShellObject parent;
|
||||||
(void)_data;
|
DiyaDashboardWidget* dashboard;
|
||||||
//g_application_quit (G_APPLICATION (gtk_window_get_application (window)));
|
DiyaTaskbarWidget* taskbar;
|
||||||
}
|
};
|
||||||
|
G_DEFINE_FINAL_TYPE(DiyaLauncher, diya_launcher, DIYA_TYPE_SHELL_OBJECT)
|
||||||
|
|
||||||
static void on_foreign_window_change(DiyaSessionShell* shell, DiyaForeignWindow * win, gpointer data)
|
enum
|
||||||
{
|
{
|
||||||
(void) data;
|
NO_PROP,
|
||||||
assert(win);
|
PROP_DASHBOARD,
|
||||||
assert(shell);
|
PROP_TASKBAR,
|
||||||
g_warning("on_foreign_window_change: WINDOW CHANGE %s, shell %s", diya_object_to_string(DIYA_OBJECT(win)), diya_object_to_string(DIYA_OBJECT(shell)));
|
N_PROPERTIES
|
||||||
}
|
};
|
||||||
|
|
||||||
static void on_foreign_window_removed(DiyaSessionShell* shell, DiyaForeignWindow * win, gpointer data)
|
static GParamSpec *g_prop[N_PROPERTIES] = {0};
|
||||||
{
|
|
||||||
(void) data;
|
|
||||||
assert(win);
|
|
||||||
assert(shell);
|
|
||||||
g_warning("on_foreign_window_removed: WINDOW REMOVED %s, shell %s", diya_object_to_string(DIYA_OBJECT(win)), diya_object_to_string(DIYA_OBJECT(shell)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void session_lock(GtkWidget *widget,gpointer data)
|
/*
|
||||||
|
static void show_windows(GtkWidget *widget,gpointer data)
|
||||||
{
|
{
|
||||||
(void) widget;
|
(void) widget;
|
||||||
g_warning("Enter session lock");
|
g_warning("Show all windows");
|
||||||
diya_session_shell_lock(data);
|
DiyaSessionShell * shell = DIYA_SESSION_SHELL(data);
|
||||||
|
assert(shell);
|
||||||
|
GHashTable* windows = NULL;
|
||||||
|
g_object_get(shell, DIYA_PROP_SESSION_WINDOWS, &windows, NULL);
|
||||||
|
assert(windows);
|
||||||
|
GHashTableIter iter;
|
||||||
|
gpointer handle;
|
||||||
|
DiyaForeignWindow* window;
|
||||||
|
g_hash_table_iter_init (&iter, windows);
|
||||||
|
while (g_hash_table_iter_next(&iter, (gpointer) &handle, (gpointer) &window))
|
||||||
|
{
|
||||||
|
g_warning("unset minimized %s", diya_object_to_string(window));
|
||||||
|
diya_foreign_window_set_state(window, DIYA_WIN_STATE_MINIMIZE, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void diya_launcher_dispose(GObject* object)
|
||||||
|
{
|
||||||
|
(void) object;
|
||||||
|
DiyaLauncher * self = DIYA_LAUNCHER(object);
|
||||||
|
g_debug("diya_launcher_dispose: %s", diya_object_to_string(object));
|
||||||
|
if(self->dashboard)
|
||||||
|
{
|
||||||
|
gtk_window_destroy(GTK_WINDOW(self->dashboard));
|
||||||
|
self->dashboard = NULL;
|
||||||
|
}
|
||||||
|
if(self->taskbar)
|
||||||
|
{
|
||||||
|
gtk_window_destroy(GTK_WINDOW(self->taskbar));
|
||||||
|
self->taskbar = NULL;
|
||||||
|
}
|
||||||
|
G_OBJECT_CLASS(diya_launcher_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_launcher_init(DiyaLauncher * self)
|
||||||
|
{
|
||||||
|
self->taskbar = NULL;
|
||||||
|
self->dashboard = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar* diya_launcher_to_string(DiyaObject* object)
|
||||||
|
{
|
||||||
|
(void) object;
|
||||||
|
return "DiyaLauncher";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void diya_launcher_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
DiyaLauncher * self = DIYA_LAUNCHER(object);
|
||||||
|
|
||||||
|
switch (property_id)
|
||||||
|
{
|
||||||
|
case PROP_DASHBOARD:
|
||||||
|
self->dashboard = g_value_get_pointer(value);
|
||||||
|
break;
|
||||||
|
case PROP_TASKBAR:
|
||||||
|
self->taskbar = g_value_get_pointer(value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_launcher_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
DiyaLauncher * self = DIYA_LAUNCHER(object);
|
||||||
|
switch (property_id)
|
||||||
|
{
|
||||||
|
case PROP_DASHBOARD:
|
||||||
|
g_value_set_pointer(value, self->dashboard);
|
||||||
|
break;
|
||||||
|
case PROP_TASKBAR:
|
||||||
|
g_value_set_pointer(value, self->taskbar);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_launcher_class_init(DiyaLauncherClass *class)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
|
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
||||||
|
|
||||||
|
gobject_class->dispose = diya_launcher_dispose;
|
||||||
|
gobject_class->set_property = diya_launcher_set_property;
|
||||||
|
gobject_class->get_property = diya_launcher_get_property;
|
||||||
|
base_class->to_string = diya_launcher_to_string;
|
||||||
|
|
||||||
|
g_prop[PROP_DASHBOARD] = g_param_spec_pointer(DIYA_PROP_LAUNCHER_DASHBOARD, NULL, "Launcher dashboard", G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
|
||||||
|
g_prop[PROP_TASKBAR] = g_param_spec_pointer(DIYA_PROP_LAUNCHER_TASKBAR, NULL, "Launcher taskbar", G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
|
||||||
|
g_object_class_install_properties (gobject_class, N_PROPERTIES, g_prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
void diya_session_shell_launcher_init(DiyaSessionShell * shell)
|
void diya_session_shell_launcher_init(DiyaSessionShell * shell)
|
||||||
{
|
{
|
||||||
assert(shell);
|
DiyaDashboardWidget* dashboard = DIYA_DASHBOARD_WIDGET(diya_shell_window_new(DIYA_TYPE_DASHBOARD_WIDGET, shell));
|
||||||
GtkApplication * app;
|
assert(dashboard);
|
||||||
g_object_get(shell, "application", &app, NULL);
|
DiyaTaskbarWidget* taskbar = DIYA_TASKBAR_WIDGET(diya_shell_window_new(DIYA_TYPE_TASKBAR_WIDGET, shell));
|
||||||
assert(app);
|
assert(taskbar);
|
||||||
GtkWindow *gtk_window = GTK_WINDOW (gtk_application_window_new (app));
|
//gtk_window_set_transient_for(GTK_WINDOW(dashboard), GTK_WINDOW(taskbar));
|
||||||
assert(gtk_window);
|
DiyaLauncher* self = DIYA_LAUNCHER(g_object_new (DIYA_TYPE_LAUNCHER, "dashboard", dashboard, "taskbar",taskbar, NULL));
|
||||||
g_object_set(shell, "launchpad", gtk_window, NULL);
|
assert(self);
|
||||||
|
g_object_bind_property(taskbar, DIYA_PROP_TASKBAR_SHOW_DASHBOARD, dashboard, DIYA_PROP_DASHBOARD_ACTIVE, G_BINDING_BIDIRECTIONAL);
|
||||||
|
g_object_set(shell, "launchpad", self, NULL);
|
||||||
|
//g_signal_connect (GTK_WINDOW(dashboard), "destroy", G_CALLBACK (on_launcher_destroy), NULL);
|
||||||
|
|
||||||
g_signal_connect (gtk_window, "destroy", G_CALLBACK (on_launcher_destroy), NULL);
|
gtk_window_present (GTK_WINDOW (taskbar));
|
||||||
// int layer shell for window
|
|
||||||
gtk_layer_init_for_window (gtk_window);
|
|
||||||
// anchor window to all edges
|
|
||||||
gtk_layer_set_anchor (gtk_window, GTK_LAYER_SHELL_EDGE_LEFT, true);
|
|
||||||
gtk_layer_set_anchor (gtk_window, GTK_LAYER_SHELL_EDGE_RIGHT, true);
|
|
||||||
gtk_layer_set_anchor (gtk_window, GTK_LAYER_SHELL_EDGE_TOP, true);
|
|
||||||
gtk_layer_set_anchor (gtk_window, GTK_LAYER_SHELL_EDGE_BOTTOM, false);
|
|
||||||
|
|
||||||
// set margin on window
|
GtkIconTheme* theme = gtk_icon_theme_get_for_display(gdk_display_get_default());
|
||||||
for (int i = 0; i < GTK_LAYER_SHELL_EDGE_ENTRY_NUMBER; i++)
|
char**icons = gtk_icon_theme_get_icon_names (theme);
|
||||||
gtk_layer_set_margin (gtk_window, i, 0);
|
g_warning("List all icons");
|
||||||
gtk_layer_set_layer (gtk_window, GTK_LAYER_SHELL_LAYER_TOP);
|
for(int i = 0; icons[i] != NULL; i++)
|
||||||
gtk_layer_set_keyboard_mode (gtk_window, GTK_LAYER_SHELL_KEYBOARD_MODE_ON_DEMAND);
|
|
||||||
gtk_layer_set_namespace (gtk_window, NAMESPACE);
|
|
||||||
// the top launcher shall be exclusive
|
|
||||||
gtk_layer_auto_exclusive_zone_enable (gtk_window);
|
|
||||||
|
|
||||||
gtk_widget_set_name(GTK_WIDGET(gtk_window),NAMESPACE);
|
|
||||||
gtk_window_set_default_size(gtk_window, 48, 48);
|
|
||||||
|
|
||||||
GtkWidget *box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
|
|
||||||
gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
|
|
||||||
gtk_window_set_child (GTK_WINDOW (gtk_window), box);
|
|
||||||
gtk_widget_set_halign (box, GTK_ALIGN_CENTER);
|
|
||||||
gtk_widget_set_valign (box, GTK_ALIGN_CENTER);
|
|
||||||
GtkWidget * button = gtk_button_new_with_label ("lock");
|
|
||||||
g_signal_connect (button, "clicked", G_CALLBACK (session_lock), shell);
|
|
||||||
gtk_box_append (GTK_BOX (box), button);
|
|
||||||
//g_signal_connect (gtk_window, "orientation-changed", G_CALLBACK (on_orientation_changed), /*data*/NULL);
|
|
||||||
gtk_window_present (GTK_WINDOW (gtk_window));
|
|
||||||
|
|
||||||
g_signal_connect (shell, "foreign-window-changed", G_CALLBACK (on_foreign_window_change), NULL);
|
|
||||||
g_signal_connect (shell, "foreign-window-removed", G_CALLBACK (on_foreign_window_removed), NULL);
|
|
||||||
|
|
||||||
GList *apps = g_app_info_get_all ();
|
|
||||||
GList * l;
|
|
||||||
for (l = apps; l != NULL; l = l->next)
|
|
||||||
{
|
{
|
||||||
gpointer element_data = l->data;
|
g_debug("ICON: %s", icons[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g_warning("%s", g_app_info_get_display_name(element_data));
|
void diya_launcher_show_dashboard(DiyaLauncher* self, gboolean value)
|
||||||
g_warning("%s", g_app_info_get_id(element_data));
|
{
|
||||||
g_warning("%s", g_app_info_get_name(element_data));
|
g_object_set(self->dashboard, DIYA_PROP_DASHBOARD_ACTIVE, value, NULL);
|
||||||
//g_warning("%s", g_app_info_get_icon(element_data));
|
|
||||||
}
|
}
|
||||||
g_list_free_full(apps, g_object_unref);
|
|
||||||
|
|
||||||
|
void diya_launcher_toggle_dashboard(DiyaLauncher* self)
|
||||||
|
{
|
||||||
|
diya_launcher_show_dashboard(self, !diya_dashboard_is_active(self->dashboard));
|
||||||
}
|
}
|
@ -1,7 +1,18 @@
|
|||||||
#ifndef DIYA_SHELL_LAUNCHER_H
|
#ifndef DIYA_SHELL_LAUNCHER_H
|
||||||
#define DIYA_SHELL_LAUNCHER_H
|
#define DIYA_SHELL_LAUNCHER_H
|
||||||
|
|
||||||
#include "session-shell.h"
|
#include "base.h"
|
||||||
|
|
||||||
|
USE_CLASS(DiyaSessionShell);
|
||||||
|
|
||||||
|
#define DIYA_PROP_LAUNCHER_DASHBOARD "dashboard"
|
||||||
|
#define DIYA_PROP_LAUNCHER_TASKBAR "taskbar"
|
||||||
|
|
||||||
|
#define DIYA_TYPE_LAUNCHER (diya_launcher_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (DiyaLauncher, diya_launcher, DIYA, LAUNCHER, DiyaShellObject)
|
||||||
|
|
||||||
|
void diya_launcher_show_dashboard(DiyaLauncher* self, gboolean value);
|
||||||
|
void diya_launcher_toggle_dashboard(DiyaLauncher* self);
|
||||||
|
|
||||||
|
|
||||||
void diya_session_shell_launcher_init(DiyaSessionShell * shell);
|
void diya_session_shell_launcher_init(DiyaSessionShell * shell);
|
||||||
|
@ -3,25 +3,39 @@
|
|||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
|
|
||||||
#include "login-shell.h"
|
#include "login-shell.h"
|
||||||
#include "virtual-keyboard.h"
|
#include "widgets/virtual-keyboard-widgets.h"
|
||||||
|
|
||||||
#define DBUS_SERVER_NAME "dev.iohub.diya.SessionManager"
|
#define DBUS_SERVER_NAME "dev.iohub.diya.SessionManager"
|
||||||
#define DBUS_SERVER_PATH "/dev/iohub/diya/SessionManager"
|
#define DBUS_SERVER_PATH "/dev/iohub/diya/SessionManager"
|
||||||
#define DBUS_SERVER_ERROR_NAME "dev.iohub.diya.SessionManager.Error"
|
#define DBUS_SERVER_ERROR_NAME "dev.iohub.diya.SessionManager.Error"
|
||||||
|
#define NAMESPACE "diya_login_shell"
|
||||||
|
|
||||||
struct _DiyaLoginShell
|
struct _DiyaLoginShell
|
||||||
{
|
{
|
||||||
DiyaShell parent_object;
|
DiyaShell parent_object;
|
||||||
GtkApplication *app;
|
|
||||||
GtkSessionLockInstance *lock;
|
GtkSessionLockInstance *lock;
|
||||||
GtkWidget *username;
|
GtkWidget *username;
|
||||||
GtkWidget *password;
|
GtkWidget *password;
|
||||||
GtkWidget *status;
|
GtkWidget *status;
|
||||||
guint bus_watch_id;
|
guint bus_watch_id;
|
||||||
|
GtkWidget *vkb_widget;
|
||||||
|
GtkWidget *revealer;
|
||||||
|
GList *windows;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_FINAL_TYPE(DiyaLoginShell, diya_login_shell, DIYA_TYPE_SHELL);
|
G_DEFINE_FINAL_TYPE(DiyaLoginShell, diya_login_shell, DIYA_TYPE_SHELL);
|
||||||
|
|
||||||
|
static void diya_login_shell_finalize(GObject *object)
|
||||||
|
{
|
||||||
|
DiyaLoginShell *self = DIYA_LOGIN_SHELL(object);
|
||||||
|
g_debug("diya_login_shell_finalize: %s", diya_object_to_string(self));
|
||||||
|
if (self->windows)
|
||||||
|
{
|
||||||
|
g_list_free(self->windows);
|
||||||
|
}
|
||||||
|
G_OBJECT_CLASS(diya_login_shell_parent_class)->finalize(object);
|
||||||
|
}
|
||||||
|
|
||||||
static void diya_login_shell_dispose(GObject *object)
|
static void diya_login_shell_dispose(GObject *object)
|
||||||
{
|
{
|
||||||
DiyaLoginShell *self = DIYA_LOGIN_SHELL(object);
|
DiyaLoginShell *self = DIYA_LOGIN_SHELL(object);
|
||||||
@ -34,47 +48,37 @@ static void diya_login_shell_dispose(GObject *object)
|
|||||||
}
|
}
|
||||||
g_object_unref(self->lock);
|
g_object_unref(self->lock);
|
||||||
}
|
}
|
||||||
|
if (self->windows)
|
||||||
|
{
|
||||||
|
// destroyed all windows and free list
|
||||||
|
GList *it = NULL;
|
||||||
|
for (it = self->windows; it; it = it->next)
|
||||||
|
{
|
||||||
|
if (it->data)
|
||||||
|
{
|
||||||
|
gtk_window_destroy(GTK_WINDOW(it->data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// g_list_free(self->windows);
|
||||||
|
}
|
||||||
if (self->bus_watch_id > 0)
|
if (self->bus_watch_id > 0)
|
||||||
{
|
{
|
||||||
g_bus_unwatch_name(self->bus_watch_id);
|
g_bus_unwatch_name(self->bus_watch_id);
|
||||||
}
|
}
|
||||||
if (self->app)
|
|
||||||
{
|
|
||||||
g_object_unref(self->app);
|
|
||||||
}
|
|
||||||
G_OBJECT_CLASS(diya_login_shell_parent_class)->dispose(object);
|
G_OBJECT_CLASS(diya_login_shell_parent_class)->dispose(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void diya_login_shell_init(DiyaLoginShell *self)
|
static void diya_login_shell_init(DiyaLoginShell *self)
|
||||||
{
|
{
|
||||||
self->app = NULL;
|
g_debug("diya_login_shell_init");
|
||||||
self->lock = gtk_session_lock_instance_new();
|
self->lock = gtk_session_lock_instance_new();
|
||||||
self->username = NULL;
|
self->username = NULL;
|
||||||
self->password = NULL;
|
self->password = NULL;
|
||||||
|
self->status = NULL;
|
||||||
|
self->windows = NULL;
|
||||||
self->bus_watch_id = 0;
|
self->bus_watch_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const gchar *diya_login_shell_to_string(DiyaObject *object)
|
|
||||||
{
|
|
||||||
(void)object;
|
|
||||||
return "Diya Login Shell";
|
|
||||||
}
|
|
||||||
|
|
||||||
static void diya_login_shell_class_init(DiyaLoginShellClass *class)
|
|
||||||
{
|
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
|
||||||
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
|
||||||
gobject_class->dispose = diya_login_shell_dispose;
|
|
||||||
// gobject_class->set_property = diya_lock_session_set_property;
|
|
||||||
// gobject_class->get_property = diya_lock_session_get_property;
|
|
||||||
|
|
||||||
|
|
||||||
//DiyaShellClass *base_shell_class = DIYA_SHELL_CLASS(class)
|
|
||||||
//base_shell_class->foreign_register = diya_session_shell_foreign_toplevel_register;
|
|
||||||
|
|
||||||
base_class->to_string = diya_login_shell_to_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void on_method_call_return(GObject *source_object, GAsyncResult *res, gpointer user_data)
|
static void on_method_call_return(GObject *source_object, GAsyncResult *res, gpointer user_data)
|
||||||
{
|
{
|
||||||
(void)source_object;
|
(void)source_object;
|
||||||
@ -103,7 +107,7 @@ static void on_method_call_return(GObject *source_object, GAsyncResult *res, gpo
|
|||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
gtk_label_set_text(GTK_LABEL(self->status), "Login successful");
|
gtk_label_set_text(GTK_LABEL(self->status), "Login successful");
|
||||||
g_application_quit(G_APPLICATION(self->app));
|
g_object_unref(self);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -174,129 +178,167 @@ static void do_login(GtkButton *button, DiyaLoginShell *self)
|
|||||||
// g_application_quit(G_APPLICATION(self->app));
|
// g_application_quit(G_APPLICATION(self->app));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void open_vkb(GtkButton *button, DiyaLoginShell *self)
|
static void add_new_monitor(DiyaLoginShell *self, GdkMonitor *monitor, gint position)
|
||||||
{
|
{
|
||||||
(void) button;
|
GtkWindow *window = GTK_WINDOW(gtk_application_window_new(diya_shell_get_application(DIYA_SHELL(self))));
|
||||||
DiyaVirtualKeyboard* vkb = diya_virtual_keyboard_new(DIYA_SHELL(self), NULL);
|
gtk_session_lock_instance_assign_window_to_monitor(self->lock, window, monitor);
|
||||||
if(!vkb)
|
gtk_widget_set_name(GTK_WIDGET(window), NAMESPACE);
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
g_warning("Sending A to: %s", diya_object_to_string(DIYA_OBJECT(vkb)));
|
|
||||||
diya_virtual_keyboard_send_key(vkb,30, VKB_KEY_STATE_PRESSED);
|
|
||||||
g_usleep(10000);
|
|
||||||
diya_virtual_keyboard_send_key(vkb,30, VKB_KEY_STATE_RELEASED);
|
|
||||||
g_usleep(10000);
|
|
||||||
// send example key
|
|
||||||
g_object_unref(vkb);
|
|
||||||
}
|
|
||||||
|
|
||||||
DiyaLoginShell *diya_login_shell_new()
|
GtkWidget *grid = gtk_grid_new();
|
||||||
{
|
gtk_window_set_child(window, grid);
|
||||||
return g_object_new(DIYA_TYPE_LOGIN_SHELL, NULL);
|
gtk_grid_set_row_homogeneous(GTK_GRID(grid), false);
|
||||||
}
|
|
||||||
|
|
||||||
void diya_login_shell_attach(DiyaLoginShell *self, GtkApplication *app)
|
|
||||||
{
|
|
||||||
self->app = app;
|
|
||||||
if (!gtk_session_lock_instance_lock(self->lock))
|
|
||||||
{
|
|
||||||
g_error("gtk_session_lock_instance_lock: Unable to lock the display");
|
|
||||||
g_object_unref(self);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GdkDisplay *display = gdk_display_get_default();
|
|
||||||
GListModel *monitors = gdk_display_get_monitors(display);
|
|
||||||
guint n_monitors = g_list_model_get_n_items(monitors);
|
|
||||||
|
|
||||||
for (guint i = 0; i < n_monitors; ++i)
|
|
||||||
{
|
|
||||||
GdkMonitor *monitor = g_list_model_get_item(monitors, i);
|
|
||||||
|
|
||||||
GtkWindow *gtk_window = GTK_WINDOW(gtk_application_window_new(app));
|
|
||||||
gtk_session_lock_instance_assign_window_to_monitor(self->lock, gtk_window, monitor);
|
|
||||||
|
|
||||||
GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||||
gtk_widget_set_halign(box, GTK_ALIGN_CENTER);
|
gtk_widget_set_halign(box, GTK_ALIGN_CENTER);
|
||||||
gtk_widget_set_valign(box, GTK_ALIGN_CENTER);
|
gtk_widget_set_valign(box, GTK_ALIGN_CENTER);
|
||||||
gtk_box_set_spacing(GTK_BOX(box), 10);
|
gtk_box_set_spacing(GTK_BOX(box), 10);
|
||||||
|
|
||||||
|
gtk_widget_set_hexpand(box, true);
|
||||||
|
gtk_widget_set_vexpand(box, true);
|
||||||
|
|
||||||
GtkWidget *label;
|
GtkWidget *label;
|
||||||
|
|
||||||
label = gtk_label_new("Please login");
|
label = gtk_label_new("Please login");
|
||||||
gtk_box_append(GTK_BOX(box), label);
|
gtk_box_append(GTK_BOX(box), label);
|
||||||
gtk_widget_add_css_class(label, "header");
|
gtk_widget_add_css_class(label, "diya-login-header");
|
||||||
|
|
||||||
GtkWidget *user_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
|
|
||||||
gtk_widget_set_valign(user_box, GTK_ALIGN_CENTER);
|
|
||||||
gtk_widget_set_halign(user_box, GTK_ALIGN_END);
|
|
||||||
gtk_box_set_spacing(GTK_BOX(user_box), 10);
|
|
||||||
|
|
||||||
|
GtkWidget *child_grid = gtk_grid_new();
|
||||||
|
gtk_grid_set_row_spacing(GTK_GRID(child_grid),10);
|
||||||
|
gtk_grid_set_column_spacing(GTK_GRID(child_grid),10);
|
||||||
label = gtk_label_new("Username");
|
label = gtk_label_new("Username");
|
||||||
gtk_box_append(GTK_BOX(user_box), label);
|
gtk_grid_attach(GTK_GRID(child_grid), label, 0, 0, 1, 1);
|
||||||
|
|
||||||
self->username = gtk_entry_new();
|
self->username = gtk_entry_new();
|
||||||
gtk_box_append(GTK_BOX(user_box), GTK_WIDGET(self->username));
|
gtk_grid_attach(GTK_GRID(child_grid), self->username, 1, 0, 1, 1);
|
||||||
|
|
||||||
gtk_box_append(GTK_BOX(box), user_box);
|
|
||||||
|
|
||||||
GtkWidget *password_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
|
|
||||||
gtk_widget_set_valign(password_box, GTK_ALIGN_CENTER);
|
|
||||||
gtk_widget_set_halign(password_box, GTK_ALIGN_END);
|
|
||||||
gtk_box_set_spacing(GTK_BOX(password_box), 10);
|
|
||||||
|
|
||||||
label = gtk_label_new("Password");
|
label = gtk_label_new("Password");
|
||||||
gtk_box_append(GTK_BOX(password_box), label);
|
gtk_grid_attach(GTK_GRID(child_grid), label, 0, 1, 1, 1);
|
||||||
|
|
||||||
self->password = gtk_password_entry_new();
|
self->password = gtk_password_entry_new();
|
||||||
gtk_box_append(GTK_BOX(password_box), GTK_WIDGET(self->password));
|
gtk_grid_attach(GTK_GRID(child_grid), self->password, 1, 1, 1, 1);
|
||||||
|
|
||||||
gtk_box_append(GTK_BOX(box), password_box);
|
gtk_box_append(GTK_BOX(box), child_grid);
|
||||||
|
|
||||||
g_signal_connect(self->username, "activate", G_CALLBACK(do_login), self);
|
g_signal_connect(self->username, "activate", G_CALLBACK(do_login), self);
|
||||||
g_signal_connect(self->password, "activate", G_CALLBACK(do_login), self);
|
g_signal_connect(self->password, "activate", G_CALLBACK(do_login), self);
|
||||||
|
|
||||||
|
child_grid = gtk_grid_new();
|
||||||
|
gtk_grid_set_column_spacing(GTK_GRID(child_grid),2);
|
||||||
|
|
||||||
GtkWidget *button = gtk_button_new_with_label("Login");
|
GtkWidget *button = gtk_button_new_with_label("Login");
|
||||||
g_signal_connect(button, "clicked", G_CALLBACK(do_login), self);
|
g_signal_connect(button, "clicked", G_CALLBACK(do_login), self);
|
||||||
//gtk_widget_set_can_focus(GTK_WIDGET(button), false);
|
gtk_widget_set_can_focus(GTK_WIDGET(button), false);
|
||||||
gtk_box_append(GTK_BOX(box), button);
|
gtk_grid_attach(GTK_GRID(child_grid), button, 0, 0, 1, 1);
|
||||||
|
|
||||||
// Not displayed, but allows testing that creating popups doesn't crash GTK
|
// Not displayed, but allows testing that creating popups doesn't crash GTK
|
||||||
gtk_widget_set_tooltip_text(button, "Login");
|
gtk_widget_set_tooltip_text(button, "Login");
|
||||||
|
gtk_widget_set_hexpand(button, true);
|
||||||
|
|
||||||
|
button = gtk_toggle_button_new_with_label("⌨");
|
||||||
|
gtk_widget_add_css_class(button, "diya-btn-show-vkb");
|
||||||
|
gtk_grid_attach(GTK_GRID(child_grid), button, 1, 0, 1, 1);
|
||||||
|
gtk_box_append(GTK_BOX(box), child_grid);
|
||||||
|
gtk_widget_set_tooltip_text(button, "Show virtual keyboard");
|
||||||
|
gtk_widget_set_can_focus(GTK_WIDGET(button), false);
|
||||||
|
|
||||||
self->status = gtk_label_new(NULL);
|
self->status = gtk_label_new(NULL);
|
||||||
gtk_box_append(GTK_BOX(box), self->status);
|
gtk_box_append(GTK_BOX(box), self->status);
|
||||||
gtk_widget_add_css_class(self->status, "status");
|
gtk_widget_add_css_class(self->status, "diya-login-status");
|
||||||
|
|
||||||
button = gtk_button_new_with_label("Show virtual keyboard");
|
gtk_grid_attach(GTK_GRID(grid), box, 0, 0, 1, 1);
|
||||||
g_signal_connect(button, "clicked", G_CALLBACK(open_vkb), self);
|
|
||||||
gtk_widget_set_can_focus(GTK_WIDGET(button), false);
|
|
||||||
gtk_box_append(GTK_BOX(box), button);
|
|
||||||
|
|
||||||
gtk_window_set_child(GTK_WINDOW(gtk_window), box);
|
box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
|
||||||
|
gtk_widget_set_valign(box, GTK_ALIGN_CENTER);
|
||||||
|
gtk_widget_set_halign(box, GTK_ALIGN_CENTER);
|
||||||
|
gtk_box_set_spacing(GTK_BOX(box), 10);
|
||||||
|
|
||||||
gtk_window_present(gtk_window);
|
self->revealer = gtk_revealer_new();
|
||||||
|
self->vkb_widget = diya_virtual_keyboard_widget_new(diya_shell_get_virtual_keyboard(DIYA_SHELL(self), g_getenv(DIYA_ENV_VKB_KEYMAP)));
|
||||||
|
gtk_revealer_set_child(GTK_REVEALER(self->revealer), self->vkb_widget);
|
||||||
|
gtk_revealer_set_reveal_child(GTK_REVEALER(self->revealer), false);
|
||||||
|
gtk_revealer_set_transition_type(GTK_REVEALER(self->revealer),GTK_REVEALER_TRANSITION_TYPE_SLIDE_UP);
|
||||||
|
gtk_box_append(GTK_BOX(box), self->revealer);
|
||||||
|
|
||||||
|
g_object_bind_property(button, "active", self->revealer, "reveal-child",G_BINDING_BIDIRECTIONAL);
|
||||||
|
//gtk_widget_set_visible(self->vkb_widget, false);
|
||||||
|
|
||||||
|
gtk_grid_attach(GTK_GRID(grid), box, 0, 1, 1, 1);
|
||||||
|
gtk_widget_set_hexpand(box, true);
|
||||||
|
gtk_widget_set_vexpand(box, false);
|
||||||
|
|
||||||
|
gtk_window_present(window);
|
||||||
|
|
||||||
|
self->windows = g_list_insert(self->windows, window, position);
|
||||||
}
|
}
|
||||||
// load xml content from gresource
|
|
||||||
GError *err = NULL;
|
static void on_monitor_changed(GListModel *monitor_lists, guint position, guint removed, guint added, gpointer object)
|
||||||
GBytes *bytes = g_resources_lookup_data("/dev/iohub/diya/shell/login-shell.css", 0, &err);
|
|
||||||
if (err != NULL)
|
|
||||||
{
|
{
|
||||||
g_critical("Unable to load CSS resource: %s", err->message);
|
g_debug("Monitor list changed at %d: added %d, removed %d", position, added, removed);
|
||||||
g_error_free(err);
|
DiyaLoginShell *self = DIYA_LOGIN_SHELL(object);
|
||||||
|
if (removed > 0)
|
||||||
|
{
|
||||||
|
for (guint i = 0; i < removed; i++)
|
||||||
|
{
|
||||||
|
GtkWindow *win = GTK_WINDOW(g_list_nth(self->windows, position));
|
||||||
|
if (win)
|
||||||
|
{
|
||||||
|
gtk_window_destroy(win);
|
||||||
|
self->windows = g_list_remove(self->windows, win);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (added > 0)
|
||||||
|
{
|
||||||
|
for (guint i = 0; i < added; i++)
|
||||||
|
{
|
||||||
|
GdkMonitor *monitor = g_list_model_get_item(monitor_lists, position + i);
|
||||||
|
add_new_monitor(self, monitor, position + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_login_on_shell_idle(DiyaShell* shell)
|
||||||
|
{
|
||||||
|
(void) shell;
|
||||||
|
g_debug("diya_login_on_shell_idle");
|
||||||
|
diya_shell_power_display(shell, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_login_on_shell_resume(DiyaShell* shell)
|
||||||
|
{
|
||||||
|
(void) shell;
|
||||||
|
g_debug("diya_login_on_shell_resume");
|
||||||
|
diya_shell_power_display(shell, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_login_shell_startup(DiyaShell *shell)
|
||||||
|
{
|
||||||
|
DiyaLoginShell *self = DIYA_LOGIN_SHELL(shell);
|
||||||
|
if (!gtk_session_lock_instance_lock(self->lock))
|
||||||
|
{
|
||||||
|
g_object_unref(self);
|
||||||
|
g_error("gtk_session_lock_instance_lock: Unable to lock the display");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
GListModel *list = gdk_display_get_monitors(gdk_display_get_default());
|
||||||
|
for (guint i = 0; i < g_list_model_get_n_items(list); i++)
|
||||||
{
|
{
|
||||||
const char *data = g_bytes_get_data(bytes, NULL);
|
GdkMonitor *monitor = g_list_model_get_item(list, i);
|
||||||
g_debug("CSS resource loaded:\n %s", data);
|
add_new_monitor(self, monitor, -1);
|
||||||
GtkCssProvider *provider = gtk_css_provider_new();
|
|
||||||
gtk_css_provider_load_from_string(provider, data);
|
|
||||||
gtk_style_context_add_provider_for_display(
|
|
||||||
gdk_display_get_default(),
|
|
||||||
GTK_STYLE_PROVIDER(provider),
|
|
||||||
GTK_STYLE_PROVIDER_PRIORITY_USER);
|
|
||||||
g_bytes_unref(bytes);
|
|
||||||
}
|
}
|
||||||
|
g_signal_connect(shell, DIYA_SIGNAL_SHELL_IDLE, G_CALLBACK(diya_login_on_shell_idle), NULL);
|
||||||
|
g_signal_connect(shell, DIYA_SIGNAL_SHELL_RESUME, G_CALLBACK(diya_login_on_shell_resume), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_login_shell_class_init(DiyaLoginShellClass *class)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
|
gobject_class->dispose = diya_login_shell_dispose;
|
||||||
|
gobject_class->finalize = diya_login_shell_finalize;
|
||||||
|
// gobject_class->set_property = diya_lock_session_set_property;
|
||||||
|
// gobject_class->get_property = diya_lock_session_get_property;
|
||||||
|
|
||||||
|
DiyaShellClass *base_shell_class = DIYA_SHELL_CLASS(class);
|
||||||
|
base_shell_class->monitor_changed_handle = on_monitor_changed;
|
||||||
|
base_shell_class->startup_handle = diya_login_shell_startup;
|
||||||
|
// base_shell_class->foreign_register = diya_session_shell_foreign_toplevel_register;
|
||||||
}
|
}
|
@ -8,8 +8,4 @@
|
|||||||
#define DIYA_TYPE_LOGIN_SHELL (diya_login_shell_get_type())
|
#define DIYA_TYPE_LOGIN_SHELL (diya_login_shell_get_type())
|
||||||
G_DECLARE_FINAL_TYPE(DiyaLoginShell, diya_login_shell, DIYA, LOGIN_SHELL, DiyaShell);
|
G_DECLARE_FINAL_TYPE(DiyaLoginShell, diya_login_shell, DIYA, LOGIN_SHELL, DiyaShell);
|
||||||
|
|
||||||
|
|
||||||
DiyaLoginShell *diya_login_shell_new();
|
|
||||||
void diya_login_shell_attach(DiyaLoginShell *self, GtkApplication *app);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
52
src/login.c
52
src/login.c
@ -2,58 +2,10 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "login-shell.h"
|
#include "login-shell.h"
|
||||||
#include "wayland.h"
|
|
||||||
|
|
||||||
static gchar **g_shell_argv;
|
|
||||||
|
|
||||||
static void activate(GtkApplication *app, void *data)
|
|
||||||
{
|
|
||||||
(void)app;
|
|
||||||
(void)data;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean restart(gpointer d)
|
|
||||||
{
|
|
||||||
(void)d;
|
|
||||||
gint i, fdlimit;
|
|
||||||
|
|
||||||
fdlimit = (int)sysconf(_SC_OPEN_MAX);
|
|
||||||
g_debug("reload: closing fd's %d to %d", STDERR_FILENO + 1, fdlimit);
|
|
||||||
for (i = STDERR_FILENO + 1; i < fdlimit; i++)
|
|
||||||
{
|
|
||||||
fcntl(i, F_SETFD, FD_CLOEXEC);
|
|
||||||
}
|
|
||||||
g_debug("reload: exec: %s", g_shell_argv[0]);
|
|
||||||
execvp(g_shell_argv[0], g_shell_argv);
|
|
||||||
exit(1);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void startup(GtkApplication *app, DiyaLoginShell* shell)
|
|
||||||
{
|
|
||||||
diya_shell_wayland_init(DIYA_SHELL(shell));
|
|
||||||
g_unix_signal_add(SIGHUP, (GSourceFunc)restart, NULL);
|
|
||||||
g_unix_signal_add(SIGINT,(GSourceFunc)g_application_quit,(void*)app);
|
|
||||||
diya_login_shell_attach(shell, app);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
g_shell_argv = g_malloc0(sizeof(gchar *) * (argc + 1));
|
DiyaLoginShell* shell = DIYA_LOGIN_SHELL(g_object_new(DIYA_TYPE_LOGIN_SHELL, "name", "dev.iohub.diya.login-shell", NULL));
|
||||||
for (int i = 0; i < argc; i++)
|
return diya_shell_run(DIYA_SHELL(shell), argc, argv);
|
||||||
{
|
|
||||||
g_shell_argv[i] = argv[i];
|
|
||||||
}
|
|
||||||
GtkApplication* app = gtk_application_new("dev.iohub.diya.login-shell", G_APPLICATION_DEFAULT_FLAGS);
|
|
||||||
|
|
||||||
DiyaLoginShell* shell = diya_login_shell_new();
|
|
||||||
|
|
||||||
g_signal_connect(app, "startup", G_CALLBACK(startup), shell);
|
|
||||||
g_signal_connect(app, "activate", G_CALLBACK(activate), shell);
|
|
||||||
// g_signal_connect(app, "shutdown", G_CALLBACK(shutdown), (void*)shell);
|
|
||||||
int status = g_application_run(G_APPLICATION(app), argc, argv);
|
|
||||||
g_warning("Exiting SHELL");
|
|
||||||
g_object_unref(shell);
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ void diya_session_shell_lock(DiyaSessionShell* shell)
|
|||||||
{
|
{
|
||||||
assert(shell);
|
assert(shell);
|
||||||
GtkSessionLockInstance * lock;
|
GtkSessionLockInstance * lock;
|
||||||
g_object_get(shell, "session-lock", &lock, NULL);
|
g_object_get(shell, DIYA_PROP_SESSION_LOCK, &lock, NULL);
|
||||||
assert(lock);
|
assert(lock);
|
||||||
if(gtk_session_lock_instance_is_locked(lock))
|
if(gtk_session_lock_instance_is_locked(lock))
|
||||||
{
|
{
|
||||||
@ -27,7 +27,7 @@ void diya_session_shell_lock(DiyaSessionShell* shell)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GtkApplication * app;
|
GtkApplication * app;
|
||||||
g_object_get(shell, "application", &app, NULL);
|
g_object_get(shell, DIYA_PROP_SHELL_APPLICATION, &app, NULL);
|
||||||
assert(app);
|
assert(app);
|
||||||
|
|
||||||
GdkDisplay *display = gdk_display_get_default();
|
GdkDisplay *display = gdk_display_get_default();
|
||||||
@ -64,7 +64,7 @@ void diya_session_shell_unlock(DiyaSessionShell* shell)
|
|||||||
{
|
{
|
||||||
assert(shell);
|
assert(shell);
|
||||||
GtkSessionLockInstance * lock;
|
GtkSessionLockInstance * lock;
|
||||||
g_object_get(shell, "session-lock", &lock, NULL);
|
g_object_get(shell, DIYA_PROP_SESSION_LOCK, &lock, NULL);
|
||||||
assert(lock);
|
assert(lock);
|
||||||
gtk_session_lock_instance_unlock(lock);
|
gtk_session_lock_instance_unlock(lock);
|
||||||
g_debug("gtk_session_lock_instance_unlock: Shell unlocked");
|
g_debug("gtk_session_lock_instance_unlock: Shell unlocked");
|
||||||
|
@ -2,15 +2,17 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <gtk4-session-lock.h>
|
#include <gtk4-session-lock.h>
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "foreign.h"
|
#include "foreign.h"
|
||||||
|
#include "background.h"
|
||||||
#define SHELL_DESCRIPTION "Diya GTK shell for wayland (diyac)"
|
#include "launcher.h"
|
||||||
|
#include "session-lock.h"
|
||||||
|
#include "idle.h"
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
NO_PROP,
|
NO_PROP,
|
||||||
SHELL_APP,
|
|
||||||
SHELL_BACKGROUND_WIDGET,
|
SHELL_BACKGROUND_WIDGET,
|
||||||
SHELL_LAUNCHPAD_WIDGET,
|
SHELL_LAUNCHPAD_WIDGET,
|
||||||
SHELL_LOCK_SESSION,
|
SHELL_LOCK_SESSION,
|
||||||
@ -23,23 +25,38 @@ static GParamSpec *shell_properties[N_PROPERTIES] = {0};
|
|||||||
struct _DiyaSessionShell
|
struct _DiyaSessionShell
|
||||||
{
|
{
|
||||||
DiyaShell parent;
|
DiyaShell parent;
|
||||||
GtkApplication* app;
|
|
||||||
GtkWindow *background;
|
GtkWindow *background;
|
||||||
GtkWindow* launcher;
|
DiyaLauncher *launcher;
|
||||||
GHashTable *windows;
|
GHashTable *windows;
|
||||||
GtkSessionLockInstance *lock;
|
GtkSessionLockInstance *lock;
|
||||||
};
|
};
|
||||||
G_DEFINE_FINAL_TYPE(DiyaSessionShell, diya_session_shell, DIYA_TYPE_SHELL)
|
G_DEFINE_FINAL_TYPE(DiyaSessionShell, diya_session_shell, DIYA_TYPE_SHELL)
|
||||||
|
|
||||||
static void diya_session_shell_dispose(GObject* object)
|
static void diya_session_shell_finalize(GObject *object)
|
||||||
{
|
{
|
||||||
DiyaSessionShell *self = DIYA_SESSION_SHELL(object);
|
DiyaSessionShell *self = DIYA_SESSION_SHELL(object);
|
||||||
g_hash_table_destroy(self->windows);
|
g_hash_table_destroy(self->windows);
|
||||||
g_debug("diya_session_shell_dispose");
|
g_debug("diya_session_shell_finalize: %s", diya_object_to_string(object));
|
||||||
|
G_OBJECT_CLASS(diya_session_shell_parent_class)->finalize(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_session_shell_dispose(GObject *object)
|
||||||
|
{
|
||||||
|
DiyaSessionShell *self = DIYA_SESSION_SHELL(object);
|
||||||
|
// g_hash_table_destroy(self->windows);
|
||||||
|
g_debug("diya_session_shell_dispose: %s", diya_object_to_string(object));
|
||||||
if (self->lock)
|
if (self->lock)
|
||||||
{
|
{
|
||||||
g_object_unref(self->lock);
|
g_object_unref(self->lock);
|
||||||
}
|
}
|
||||||
|
if (self->background)
|
||||||
|
{
|
||||||
|
gtk_window_destroy(self->background);
|
||||||
|
}
|
||||||
|
if (self->launcher)
|
||||||
|
{
|
||||||
|
g_object_unref(self->launcher);
|
||||||
|
}
|
||||||
G_OBJECT_CLASS(diya_session_shell_parent_class)->dispose(object);
|
G_OBJECT_CLASS(diya_session_shell_parent_class)->dispose(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,10 +65,6 @@ static void diya_session_shell_set_property(GObject *object, guint property_id,
|
|||||||
DiyaSessionShell *self = DIYA_SESSION_SHELL(object);
|
DiyaSessionShell *self = DIYA_SESSION_SHELL(object);
|
||||||
switch (property_id)
|
switch (property_id)
|
||||||
{
|
{
|
||||||
case SHELL_APP:
|
|
||||||
self->app = g_value_get_pointer(value);
|
|
||||||
assert(self->app);
|
|
||||||
break;
|
|
||||||
case SHELL_BACKGROUND_WIDGET:
|
case SHELL_BACKGROUND_WIDGET:
|
||||||
self->background = g_value_get_pointer(value);
|
self->background = g_value_get_pointer(value);
|
||||||
break;
|
break;
|
||||||
@ -72,9 +85,6 @@ static void diya_session_shell_get_property(GObject *object, guint property_id,
|
|||||||
DiyaSessionShell *self = DIYA_SESSION_SHELL(object);
|
DiyaSessionShell *self = DIYA_SESSION_SHELL(object);
|
||||||
switch (property_id)
|
switch (property_id)
|
||||||
{
|
{
|
||||||
case SHELL_APP:
|
|
||||||
g_value_set_pointer(value, self->app);
|
|
||||||
break;
|
|
||||||
case SHELL_BACKGROUND_WIDGET:
|
case SHELL_BACKGROUND_WIDGET:
|
||||||
g_value_set_pointer(value, self->background);
|
g_value_set_pointer(value, self->background);
|
||||||
break;
|
break;
|
||||||
@ -95,34 +105,90 @@ static void diya_session_shell_get_property(GObject *object, guint property_id,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const gchar* diya_session_shell_to_string(DiyaObject* object)
|
static void diya_session_on_key_pressed(DiyaShell* shell, struct xkb_keymap *xkb_keymap, struct xkb_state *xkb_state, uint32_t key, uint32_t time, gpointer userdata)
|
||||||
{
|
{
|
||||||
(void) object;
|
(void) xkb_keymap;
|
||||||
return SHELL_DESCRIPTION;
|
(void) userdata;
|
||||||
|
(void) time;
|
||||||
|
DiyaSessionShell* self = DIYA_SESSION_SHELL(shell);
|
||||||
|
uint32_t keycode = key + 8;
|
||||||
|
xkb_keysym_t sym = xkb_state_key_get_one_sym(xkb_state, keycode);
|
||||||
|
g_debug("Key press %d", sym);
|
||||||
|
switch(sym)
|
||||||
|
{
|
||||||
|
case XKB_KEY_Escape:
|
||||||
|
diya_launcher_show_dashboard(self->launcher, false);
|
||||||
|
break;
|
||||||
|
case XKB_KEY_space:
|
||||||
|
if(xkb_state_mod_name_is_active(xkb_state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE)) {
|
||||||
|
diya_launcher_toggle_dashboard(self->launcher);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
char buf[128];
|
||||||
|
xkb_keysym_get_name(sym, buf, sizeof(buf));
|
||||||
|
g_warning("key-pressed (%d): sym: %-12s (%d)", time, buf, sym);
|
||||||
|
xkb_state_key_get_utf8(xkb_state, keycode, buf, sizeof(buf));
|
||||||
|
g_warning("\tutf8: '%s'", buf);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_session_on_shell_idle(DiyaShell* shell)
|
||||||
|
{
|
||||||
|
(void) shell;
|
||||||
|
g_debug("diya_session_on_shell_idle");
|
||||||
|
diya_shell_power_display(shell, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_session_on_shell_resume(DiyaShell* shell)
|
||||||
|
{
|
||||||
|
(void) shell;
|
||||||
|
g_debug("diya_session_on_shell_resume");
|
||||||
|
diya_shell_power_display(shell, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_session_shell_startup(DiyaShell *shell)
|
||||||
|
{
|
||||||
|
DiyaSessionShell* self = DIYA_SESSION_SHELL(shell);
|
||||||
|
diya_session_shell_init_background(self);
|
||||||
|
diya_session_shell_launcher_init(self);
|
||||||
|
g_signal_connect(shell, DIYA_SIGNAL_SHELL_KEY_PRESSED, G_CALLBACK(diya_session_on_key_pressed), NULL);
|
||||||
|
g_signal_connect(shell, DIYA_SIGNAL_SHELL_IDLE, G_CALLBACK(diya_session_on_shell_idle), NULL);
|
||||||
|
g_signal_connect(shell, DIYA_SIGNAL_SHELL_RESUME, G_CALLBACK(diya_session_on_shell_resume), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_session_shell_active(DiyaShell *shell)
|
||||||
|
{
|
||||||
|
diya_shell_monitor_input(shell);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void diya_session_shell_class_init(DiyaSessionShellClass *class)
|
static void diya_session_shell_class_init(DiyaSessionShellClass *class)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
// DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
||||||
|
|
||||||
DiyaShellClass *base_shell_class = DIYA_SHELL_CLASS(class);
|
DiyaShellClass *base_shell_class = DIYA_SHELL_CLASS(class);
|
||||||
base_shell_class->foreign_register = diya_session_shell_foreign_toplevel_register;
|
base_shell_class->foreign_register = diya_session_shell_foreign_toplevel_register;
|
||||||
|
base_shell_class->startup_handle = diya_session_shell_startup;
|
||||||
|
base_shell_class->active_handle = diya_session_shell_active;
|
||||||
|
|
||||||
base_class->to_string = diya_session_shell_to_string;
|
/// base_class->to_string = diya_session_shell_to_string;
|
||||||
gobject_class->dispose = diya_session_shell_dispose;
|
gobject_class->dispose = diya_session_shell_dispose;
|
||||||
|
gobject_class->finalize = diya_session_shell_finalize;
|
||||||
gobject_class->set_property = diya_session_shell_set_property;
|
gobject_class->set_property = diya_session_shell_set_property;
|
||||||
gobject_class->get_property = diya_session_shell_get_property;
|
gobject_class->get_property = diya_session_shell_get_property;
|
||||||
|
|
||||||
shell_properties[SHELL_APP] = g_param_spec_pointer("application", NULL, "Shell application", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
shell_properties[SHELL_BACKGROUND_WIDGET] = g_param_spec_pointer(DIYA_PROP_SESSION_BACKGROUND, NULL, "Shell background widget", G_PARAM_READWRITE);
|
||||||
shell_properties[SHELL_BACKGROUND_WIDGET] = g_param_spec_pointer("background", NULL, "Shell background widget", G_PARAM_READWRITE );
|
shell_properties[SHELL_LAUNCHPAD_WIDGET] = g_param_spec_pointer(DIYA_PROP_SESSION_LAUNCHPAD, NULL, "Shell launchpad", G_PARAM_READWRITE);
|
||||||
shell_properties[SHELL_LAUNCHPAD_WIDGET] = g_param_spec_pointer("launchpad", NULL, "Shell launchpad", G_PARAM_READWRITE );
|
shell_properties[SHELL_LOCK_SESSION] = g_param_spec_pointer(DIYA_PROP_SESSION_LOCK, NULL, "Shell lock session", G_PARAM_READABLE);
|
||||||
shell_properties[SHELL_LOCK_SESSION] = g_param_spec_pointer("session-lock", NULL, "Shell lock session", G_PARAM_READABLE );
|
shell_properties[SHELL_WINDOWS] = g_param_spec_pointer(DIYA_PROP_SESSION_WINDOWS, NULL, "Shell foreign windows", G_PARAM_READABLE);
|
||||||
shell_properties[SHELL_WINDOWS] = g_param_spec_pointer("windows", NULL, "Shell foreign windows", G_PARAM_READABLE);
|
|
||||||
|
|
||||||
g_object_class_install_properties(gobject_class, N_PROPERTIES, shell_properties);
|
g_object_class_install_properties(gobject_class, N_PROPERTIES, shell_properties);
|
||||||
|
|
||||||
g_signal_new("foreign-window-changed",
|
g_signal_new(DIYA_SIGNAL_FOREIGN_WINDOW_CHANGED,
|
||||||
DIYA_TYPE_SESSION_SHELL,
|
DIYA_TYPE_SESSION_SHELL,
|
||||||
G_SIGNAL_DETAILED |
|
G_SIGNAL_DETAILED |
|
||||||
G_SIGNAL_ACTION |
|
G_SIGNAL_ACTION |
|
||||||
@ -134,7 +200,20 @@ static void diya_session_shell_class_init(DiyaSessionShellClass *class)
|
|||||||
G_TYPE_NONE,
|
G_TYPE_NONE,
|
||||||
1,
|
1,
|
||||||
G_TYPE_POINTER);
|
G_TYPE_POINTER);
|
||||||
g_signal_new("foreign-window-removed",
|
g_signal_new(DIYA_SIGNAL_FOREIGN_WINDOW_STATE_CHANGED,
|
||||||
|
DIYA_TYPE_SESSION_SHELL,
|
||||||
|
G_SIGNAL_DETAILED |
|
||||||
|
G_SIGNAL_ACTION |
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
2,
|
||||||
|
G_TYPE_POINTER,
|
||||||
|
G_TYPE_UINT);
|
||||||
|
g_signal_new(DIYA_SIGNAL_FOREIGN_WINDOW_ADDED,
|
||||||
DIYA_TYPE_SESSION_SHELL,
|
DIYA_TYPE_SESSION_SHELL,
|
||||||
G_SIGNAL_DETAILED |
|
G_SIGNAL_DETAILED |
|
||||||
G_SIGNAL_ACTION |
|
G_SIGNAL_ACTION |
|
||||||
@ -146,7 +225,19 @@ static void diya_session_shell_class_init(DiyaSessionShellClass *class)
|
|||||||
G_TYPE_NONE,
|
G_TYPE_NONE,
|
||||||
1,
|
1,
|
||||||
G_TYPE_POINTER);
|
G_TYPE_POINTER);
|
||||||
g_signal_new("session-locked",
|
g_signal_new(DIYA_SIGNAL_FOREIGN_WINDOW_REMOVED,
|
||||||
|
DIYA_TYPE_SESSION_SHELL,
|
||||||
|
G_SIGNAL_DETAILED |
|
||||||
|
G_SIGNAL_ACTION |
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
1,
|
||||||
|
G_TYPE_POINTER);
|
||||||
|
g_signal_new(DIYA_SIGNAL_SESSION_LOCKED,
|
||||||
DIYA_TYPE_SESSION_SHELL,
|
DIYA_TYPE_SESSION_SHELL,
|
||||||
G_SIGNAL_DETAILED |
|
G_SIGNAL_DETAILED |
|
||||||
G_SIGNAL_ACTION |
|
G_SIGNAL_ACTION |
|
||||||
@ -157,7 +248,7 @@ static void diya_session_shell_class_init(DiyaSessionShellClass *class)
|
|||||||
NULL,
|
NULL,
|
||||||
G_TYPE_NONE,
|
G_TYPE_NONE,
|
||||||
0);
|
0);
|
||||||
g_signal_new("session-unlocked",
|
g_signal_new(DIYA_SIGNAL_SESSION_UNLOCKED,
|
||||||
DIYA_TYPE_SESSION_SHELL,
|
DIYA_TYPE_SESSION_SHELL,
|
||||||
G_SIGNAL_DETAILED |
|
G_SIGNAL_DETAILED |
|
||||||
G_SIGNAL_ACTION |
|
G_SIGNAL_ACTION |
|
||||||
@ -170,28 +261,20 @@ static void diya_session_shell_class_init(DiyaSessionShellClass *class)
|
|||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_session_locked(GtkSessionLockInstance *lock, DiyaSessionShell *shell) {
|
static void on_session_locked(GtkSessionLockInstance *lock, DiyaSessionShell *shell)
|
||||||
|
{
|
||||||
(void)lock;
|
(void)lock;
|
||||||
assert(shell);
|
assert(shell);
|
||||||
g_message("Session locked successfully");
|
g_message("Session locked successfully");
|
||||||
g_signal_emit_by_name(shell, "session-locked");
|
g_signal_emit_by_name(shell, DIYA_SIGNAL_SESSION_LOCKED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static void on_session_unlocked(GtkSessionLockInstance *lock, DiyaSessionShell *shell)
|
||||||
static void failed(GtkSessionLockInstance *lock, void *data) {
|
{
|
||||||
(void)lock;
|
|
||||||
(void)data;
|
|
||||||
|
|
||||||
g_critical("The session could not be locked");
|
|
||||||
g_application_quit(G_APPLICATION(app));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void on_session_unlocked(GtkSessionLockInstance *lock, DiyaSessionShell *shell) {
|
|
||||||
(void)lock;
|
(void)lock;
|
||||||
assert(shell);
|
assert(shell);
|
||||||
g_message("Session unlocked");
|
g_message("Session unlocked");
|
||||||
g_signal_emit_by_name(shell, "session-unlocked");
|
g_signal_emit_by_name(shell, DIYA_SIGNAL_SESSION_UNLOCKED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void diya_session_shell_init(DiyaSessionShell *self)
|
static void diya_session_shell_init(DiyaSessionShell *self)
|
||||||
@ -213,7 +296,7 @@ DiyaForeignWindow* diya_session_shell_get_window(DiyaSessionShell * shell, gpoin
|
|||||||
gboolean diya_session_shell_add_window(DiyaSessionShell *shell, DiyaForeignWindow *win)
|
gboolean diya_session_shell_add_window(DiyaSessionShell *shell, DiyaForeignWindow *win)
|
||||||
{
|
{
|
||||||
gpointer handle;
|
gpointer handle;
|
||||||
g_object_get(win, "handle", &handle, NULL);
|
g_object_get(win, DIYA_PROP_FOREIGN_WINDOW_HANDLE, &handle, NULL);
|
||||||
assert(handle);
|
assert(handle);
|
||||||
return g_hash_table_insert(shell->windows, handle, win);
|
return g_hash_table_insert(shell->windows, handle, win);
|
||||||
}
|
}
|
||||||
@ -221,7 +304,7 @@ gboolean diya_session_shell_add_window(DiyaSessionShell * shell, DiyaForeignWind
|
|||||||
gboolean diya_session_shell_remove_window(DiyaSessionShell *shell, DiyaForeignWindow *win)
|
gboolean diya_session_shell_remove_window(DiyaSessionShell *shell, DiyaForeignWindow *win)
|
||||||
{
|
{
|
||||||
gpointer handle;
|
gpointer handle;
|
||||||
g_object_get(win, "handle", &handle, NULL);
|
g_object_get(win, DIYA_PROP_FOREIGN_WINDOW_HANDLE, &handle, NULL);
|
||||||
assert(handle);
|
assert(handle);
|
||||||
return g_hash_table_remove(shell->windows, handle);
|
return g_hash_table_remove(shell->windows, handle);
|
||||||
}
|
}
|
||||||
@ -232,10 +315,6 @@ void diya_session_shell_remove_all_windows(DiyaSessionShell * shell)
|
|||||||
shell->windows = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref);
|
shell->windows = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref);
|
||||||
}
|
}
|
||||||
|
|
||||||
DiyaSessionShell * diya_session_shell_new(GtkApplication * app)
|
|
||||||
{
|
|
||||||
return DIYA_SESSION_SHELL(g_object_new(DIYA_TYPE_SESSION_SHELL,"application",app, NULL));
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
static void on_orientation_changed (GtkWindow *window, WindowOrientation orientation, ToplevelData *data)
|
static void on_orientation_changed (GtkWindow *window, WindowOrientation orientation, ToplevelData *data)
|
||||||
{
|
{
|
||||||
|
@ -5,16 +5,25 @@
|
|||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "base.h"
|
#include "base.h"
|
||||||
|
|
||||||
|
#define DIYA_SIGNAL_FOREIGN_WINDOW_CHANGED "foreign-window-changed"
|
||||||
|
#define DIYA_SIGNAL_FOREIGN_WINDOW_STATE_CHANGED "foreign-window-state-changed"
|
||||||
|
#define DIYA_SIGNAL_FOREIGN_WINDOW_ADDED "foreign-window-added"
|
||||||
|
#define DIYA_SIGNAL_FOREIGN_WINDOW_REMOVED "foreign-window-removed"
|
||||||
|
#define DIYA_SIGNAL_SESSION_LOCKED "session-locked"
|
||||||
|
#define DIYA_SIGNAL_SESSION_UNLOCKED "session-unlocked"
|
||||||
|
|
||||||
|
#define DIYA_PROP_SESSION_LAUNCHPAD "launchpad"
|
||||||
|
#define DIYA_PROP_SESSION_BACKGROUND "background"
|
||||||
|
#define DIYA_PROP_SESSION_LOCK "session-lock"
|
||||||
|
#define DIYA_PROP_SESSION_WINDOWS "windows"
|
||||||
|
|
||||||
#define DIYA_TYPE_SESSION_SHELL (diya_session_shell_get_type ())
|
#define DIYA_TYPE_SESSION_SHELL (diya_session_shell_get_type ())
|
||||||
G_DECLARE_FINAL_TYPE (DiyaSessionShell, diya_session_shell, DIYA, SESSION_SHELL, DiyaShell)
|
G_DECLARE_FINAL_TYPE (DiyaSessionShell, diya_session_shell, DIYA, SESSION_SHELL, DiyaShell)
|
||||||
|
|
||||||
#define DIYA_TYPE_FOREIGN_WINDOW (diya_foreign_window_get_type ())
|
USE_CLASS(DiyaForeignWindow);
|
||||||
G_DECLARE_FINAL_TYPE (DiyaForeignWindow, diya_foreign_window, DIYA, FOREIGN_WINDOW, DiyaShellObject)
|
|
||||||
|
|
||||||
DiyaForeignWindow* diya_session_shell_get_window(DiyaSessionShell * shell, gpointer handle);
|
DiyaForeignWindow* diya_session_shell_get_window(DiyaSessionShell * shell, gpointer handle);
|
||||||
gboolean diya_session_shell_add_window(DiyaSessionShell * shell, DiyaForeignWindow * win);
|
gboolean diya_session_shell_add_window(DiyaSessionShell * shell, DiyaForeignWindow * win);
|
||||||
gboolean diya_session_shell_remove_window(DiyaSessionShell * shell, DiyaForeignWindow * win);
|
gboolean diya_session_shell_remove_window(DiyaSessionShell * shell, DiyaForeignWindow * win);
|
||||||
void diya_session_shell_remove_all_windows(DiyaSessionShell * shell);
|
void diya_session_shell_remove_all_windows(DiyaSessionShell * shell);
|
||||||
|
|
||||||
DiyaSessionShell * diya_session_shell_new(GtkApplication * app);
|
|
||||||
#endif
|
#endif
|
@ -1,61 +1,6 @@
|
|||||||
#include <glib-unix.h>
|
#include <glib-unix.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "shell.h"
|
#include "session-shell.h"
|
||||||
#include "background.h"
|
|
||||||
#include "launcher.h"
|
|
||||||
#include "wayland.h"
|
|
||||||
#include "foreign.h"
|
|
||||||
#include "session-lock.h"
|
|
||||||
|
|
||||||
static gchar **g_shell_argv;
|
|
||||||
|
|
||||||
static void activate(GtkApplication *app, void *data)
|
|
||||||
{
|
|
||||||
(void)app;
|
|
||||||
(void)data;
|
|
||||||
|
|
||||||
DiyaSessionShell *shell = data;
|
|
||||||
diya_session_shell_lock(shell);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean restart(gpointer d)
|
|
||||||
{
|
|
||||||
(void)d;
|
|
||||||
gint i, fdlimit;
|
|
||||||
|
|
||||||
fdlimit = (int)sysconf(_SC_OPEN_MAX);
|
|
||||||
g_debug("reload: closing fd's %d to %d", STDERR_FILENO + 1, fdlimit);
|
|
||||||
for (i = STDERR_FILENO + 1; i < fdlimit; i++)
|
|
||||||
{
|
|
||||||
fcntl(i, F_SETFD, FD_CLOEXEC);
|
|
||||||
}
|
|
||||||
g_debug("reload: exec: %s", g_shell_argv[0]);
|
|
||||||
execvp(g_shell_argv[0], g_shell_argv);
|
|
||||||
exit(1);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void startup(GtkApplication *app, void *data)
|
|
||||||
{
|
|
||||||
DiyaSessionShell *shell = data;
|
|
||||||
|
|
||||||
diya_session_shell_launcher_init(shell);
|
|
||||||
diya_session_shell_init_background(shell);
|
|
||||||
diya_shell_wayland_init(DIYA_SHELL(shell));
|
|
||||||
|
|
||||||
GtkCssProvider *provider = gtk_css_provider_new();
|
|
||||||
const char *css = "#launcher {background-color: red;} #background {background-image:url(\"file:///etc/xdg/labwc/wpp.jpg\");background-size: cover;}";
|
|
||||||
gtk_css_provider_load_from_string(provider, css);
|
|
||||||
gtk_style_context_add_provider_for_display(
|
|
||||||
gdk_display_get_default(), GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
|
|
||||||
// g_signal_connect (win, "destroy", G_CALLBACK (before_destroy), provider);
|
|
||||||
g_object_unref(provider);
|
|
||||||
// CSS support
|
|
||||||
// set color for it
|
|
||||||
// g_timeout_add (100,(GSourceFunc )shell_timer,NULL);
|
|
||||||
g_unix_signal_add(SIGHUP, (GSourceFunc)restart, NULL);
|
|
||||||
g_unix_signal_add(SIGINT,(GSourceFunc)g_application_quit,(void*)app);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void session_locked(DiyaSessionShell* shell, void* data)
|
static void session_locked(DiyaSessionShell* shell, void* data)
|
||||||
{
|
{
|
||||||
@ -73,21 +18,8 @@ static void session_unlocked(DiyaSessionShell* shell, void* data)
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
g_shell_argv = g_malloc0(sizeof(gchar *) * (argc + 1));
|
DiyaSessionShell *shell = DIYA_SESSION_SHELL(g_object_new(DIYA_TYPE_SESSION_SHELL, "name","dev.iohub.diya.session-shell", NULL));
|
||||||
for (int i = 0; i < argc; i++)
|
g_signal_connect(shell, DIYA_SIGNAL_SESSION_LOCKED, G_CALLBACK(session_locked), NULL);
|
||||||
{
|
g_signal_connect(shell, DIYA_SIGNAL_SESSION_UNLOCKED, G_CALLBACK(session_unlocked), NULL);
|
||||||
g_shell_argv[i] = argv[i];
|
return diya_shell_run(DIYA_SHELL(shell), argc, argv);
|
||||||
}
|
|
||||||
GtkApplication *app = gtk_application_new("dev.iohub.diya.shell", G_APPLICATION_DEFAULT_FLAGS);
|
|
||||||
DiyaSessionShell *shell = diya_session_shell_new(app);
|
|
||||||
g_signal_connect(app, "startup", G_CALLBACK(startup), (void *)shell);
|
|
||||||
g_signal_connect(app, "activate", G_CALLBACK(activate), (void *)shell);
|
|
||||||
g_signal_connect(shell, "session-locked", G_CALLBACK(session_locked), NULL);
|
|
||||||
g_signal_connect(shell, "session-unlocked", G_CALLBACK(session_unlocked), NULL);
|
|
||||||
// g_signal_connect(app, "shutdown", G_CALLBACK(shutdown), (void*)shell);
|
|
||||||
int status = g_application_run(G_APPLICATION(app), argc, argv);
|
|
||||||
g_warning("Exiting SHELL");
|
|
||||||
g_object_unref(app);
|
|
||||||
g_object_unref(shell);
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
589
src/shell.c
589
src/shell.c
@ -1,26 +1,65 @@
|
|||||||
|
#include <glib-unix.h>
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "wayland.h"
|
#include "wayland.h"
|
||||||
#include "virtual-keyboard.h"
|
#include "virtual-keyboard.h"
|
||||||
|
#include "files-monior.h"
|
||||||
|
#include "input.h"
|
||||||
|
#include "idle.h"
|
||||||
|
#include "wlr-output-power-management-unstable-v1.h"
|
||||||
|
#include <wayland-client-protocol.h>
|
||||||
|
#include <gdk/wayland/gdkwayland.h>
|
||||||
|
|
||||||
|
#define DEFAULT_IDLE_TIMEOUT 60*1000 // 1m
|
||||||
|
|
||||||
|
#define diya_shell_config_theme(priv) (g_strconcat(g_get_home_dir(), "/.themes/", priv->theme ? priv->theme : "default", "/gtk-4.0/gtk.css", NULL))
|
||||||
|
#define diya_shell_config_theme_dir(priv) (g_strconcat(g_get_home_dir(), "/.themes/", priv->theme ? priv->theme : "default", "/gtk-4.0", NULL))
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
NO_PROP,
|
NO_PROP,
|
||||||
PROP_SHELL_WAYLAND,
|
PROP_SHELL_WAYLAND,
|
||||||
|
PROP_SHELL_APP,
|
||||||
|
PROP_SHELL_NAME,
|
||||||
|
PROP_SHELL_THEME,
|
||||||
|
PROP_SHELL_IDLE_TO,
|
||||||
N_PROPERTIES
|
N_PROPERTIES
|
||||||
};
|
};
|
||||||
|
|
||||||
static GParamSpec *shell_properties[N_PROPERTIES] = {0};
|
static GParamSpec *shell_properties[N_PROPERTIES] = {0};
|
||||||
|
|
||||||
|
|
||||||
typedef struct _DiyaShellPrivate
|
typedef struct _DiyaShellPrivate
|
||||||
{
|
{
|
||||||
DiyaObject parent;
|
DiyaObject parent;
|
||||||
DiyaWayland *wayland;
|
DiyaWayland *wayland;
|
||||||
DiyaVirtualKeyboard* vkb;
|
GtkApplication *app;
|
||||||
|
gchar *name;
|
||||||
|
GHashTable *vkbs;
|
||||||
|
GtkCssProvider *css_provider;
|
||||||
|
DiyaInput *input;
|
||||||
|
DiyaFilesMonitor *files_watchdog;
|
||||||
|
gchar *theme;
|
||||||
|
DiyaIdleNotification *idle_notif;
|
||||||
} DiyaShellPrivate;
|
} DiyaShellPrivate;
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE(DiyaShell, diya_shell, DIYA_TYPE_OBJECT);
|
G_DEFINE_TYPE_WITH_PRIVATE(DiyaShell, diya_shell, DIYA_TYPE_OBJECT);
|
||||||
|
|
||||||
|
static void diya_shell_finalize(GObject *object)
|
||||||
|
{
|
||||||
|
g_debug("diya_shell_finalize: %s", diya_object_to_string(object));
|
||||||
|
DiyaShell *self = DIYA_SHELL(object);
|
||||||
|
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
|
||||||
|
if (priv->name)
|
||||||
|
{
|
||||||
|
g_free(priv->name);
|
||||||
|
priv->name = NULL;
|
||||||
|
}
|
||||||
|
if (priv->theme)
|
||||||
|
{
|
||||||
|
g_free(priv->theme);
|
||||||
|
priv->name = NULL;
|
||||||
|
}
|
||||||
|
g_hash_table_destroy(priv->vkbs);
|
||||||
|
G_OBJECT_CLASS(diya_shell_parent_class)->finalize(object);
|
||||||
|
}
|
||||||
|
|
||||||
static void diya_shell_dispose(GObject *object)
|
static void diya_shell_dispose(GObject *object)
|
||||||
{
|
{
|
||||||
@ -31,7 +70,193 @@ static void diya_shell_dispose(GObject* object)
|
|||||||
{
|
{
|
||||||
g_object_unref(priv->wayland);
|
g_object_unref(priv->wayland);
|
||||||
}
|
}
|
||||||
|
if (priv->css_provider)
|
||||||
|
{
|
||||||
|
g_object_unref(priv->css_provider);
|
||||||
|
}
|
||||||
|
if (priv->input)
|
||||||
|
{
|
||||||
|
g_object_unref(priv->input);
|
||||||
|
}
|
||||||
|
if (priv->files_watchdog)
|
||||||
|
{
|
||||||
|
g_object_unref(priv->files_watchdog);
|
||||||
|
priv->files_watchdog = NULL;
|
||||||
|
}
|
||||||
|
if (priv->idle_notif)
|
||||||
|
{
|
||||||
|
g_object_unref(priv->idle_notif);
|
||||||
|
priv->idle_notif = NULL;
|
||||||
|
}
|
||||||
G_OBJECT_CLASS(diya_shell_parent_class)->dispose(object);
|
G_OBJECT_CLASS(diya_shell_parent_class)->dispose(object);
|
||||||
|
if (priv->app)
|
||||||
|
{
|
||||||
|
g_application_quit(G_APPLICATION(priv->app));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_shell_reload_theme(DiyaShell *shell)
|
||||||
|
{
|
||||||
|
DiyaShellPrivate *priv = diya_shell_get_instance_private(shell);
|
||||||
|
|
||||||
|
if (priv->css_provider)
|
||||||
|
{
|
||||||
|
gtk_style_context_remove_provider_for_display(gdk_display_get_default(), GTK_STYLE_PROVIDER(priv->css_provider));
|
||||||
|
g_object_unref(priv->css_provider);
|
||||||
|
priv->css_provider = NULL;
|
||||||
|
}
|
||||||
|
priv->css_provider = gtk_css_provider_new();
|
||||||
|
|
||||||
|
gchar *css_file = diya_shell_config_theme(priv);
|
||||||
|
g_debug("diya_shell_reload_theme: Looking for css file: %s", css_file);
|
||||||
|
if (g_file_test(css_file, G_FILE_TEST_EXISTS))
|
||||||
|
{
|
||||||
|
GFile *file = g_file_new_for_path(css_file);
|
||||||
|
gtk_css_provider_load_from_file(priv->css_provider, file);
|
||||||
|
g_object_unref(file);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_warning("diya_shell_reload_theme: Unable to load CSS from file: %s. Fallback to default theme", css_file);
|
||||||
|
gchar *css_resource = g_strconcat("/dev/iohub/diya/shell/css/", priv->name, ".css", NULL);
|
||||||
|
gtk_css_provider_load_from_resource(priv->css_provider, css_resource);
|
||||||
|
g_free(css_resource);
|
||||||
|
}
|
||||||
|
g_free(css_file);
|
||||||
|
gtk_style_context_add_provider_for_display(
|
||||||
|
gdk_display_get_default(),
|
||||||
|
GTK_STYLE_PROVIDER(priv->css_provider),
|
||||||
|
GTK_STYLE_PROVIDER_PRIORITY_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_shell_reload(DiyaShell *self)
|
||||||
|
{
|
||||||
|
diya_shell_reload_theme(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_diya_shell_theme_file_changed(GFileMonitor *monitor, GFile *file, GFile *other, GFileMonitorEvent evtype, gpointer user_data)
|
||||||
|
{
|
||||||
|
(void)monitor;
|
||||||
|
DiyaShell *shell = user_data;
|
||||||
|
char *fpath = g_file_get_path(file);
|
||||||
|
char *opath = NULL;
|
||||||
|
g_debug("%s event %x", fpath, evtype);
|
||||||
|
if (other)
|
||||||
|
{
|
||||||
|
opath = g_file_get_path(other);
|
||||||
|
}
|
||||||
|
switch (evtype)
|
||||||
|
{
|
||||||
|
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
|
||||||
|
case G_FILE_MONITOR_EVENT_DELETED:
|
||||||
|
case G_FILE_MONITOR_EVENT_RENAMED:
|
||||||
|
case G_FILE_MONITOR_EVENT_MOVED_IN:
|
||||||
|
case G_FILE_MONITOR_EVENT_MOVED_OUT:
|
||||||
|
// case G_FILE_MONITOR_EVENT_CHANGED:
|
||||||
|
// case G_FILE_MONITOR_EVENT_CREATED:
|
||||||
|
diya_shell_reload_theme(shell);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (opath)
|
||||||
|
{
|
||||||
|
g_free(opath);
|
||||||
|
}
|
||||||
|
g_free(fpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_shell_idle(DiyaIdleNotification *notif, DiyaShell *shell)
|
||||||
|
{
|
||||||
|
assert(DIYA_IS_IDLE_NOTIFICATION(notif));
|
||||||
|
g_signal_emit_by_name(shell, DIYA_SIGNAL_SHELL_IDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_shell_resume(DiyaIdleNotification *notif, DiyaShell *shell)
|
||||||
|
{
|
||||||
|
assert(DIYA_IS_IDLE_NOTIFICATION(notif));
|
||||||
|
g_signal_emit_by_name(shell, DIYA_SIGNAL_SHELL_RESUME);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_gtk_app_startup(GtkApplication *app, void *data)
|
||||||
|
{
|
||||||
|
(void)app;
|
||||||
|
DiyaShell *shell = data;
|
||||||
|
DiyaShellPrivate *priv = diya_shell_get_instance_private(shell);
|
||||||
|
priv->wayland = diya_wayland_new(DIYA_SHELL(shell));
|
||||||
|
DiyaShellClass *class = DIYA_SHELL_GET_CLASS(shell);
|
||||||
|
|
||||||
|
// read envar
|
||||||
|
const char *default_theme = g_getenv(DIYA_ENV_THEME);
|
||||||
|
if (default_theme)
|
||||||
|
{
|
||||||
|
priv->theme = g_strdup(default_theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar *dir = diya_shell_config_theme_dir(priv);
|
||||||
|
diya_shell_watch_file(shell, dir, G_CALLBACK(on_diya_shell_theme_file_changed), (gpointer)shell);
|
||||||
|
g_free(dir);
|
||||||
|
|
||||||
|
diya_shell_reload(shell);
|
||||||
|
if (class->startup_handle)
|
||||||
|
{
|
||||||
|
class->startup_handle(shell);
|
||||||
|
}
|
||||||
|
if (class->monitor_changed_handle)
|
||||||
|
{
|
||||||
|
GListModel *monitor_list = gdk_display_get_monitors(gdk_display_get_default());
|
||||||
|
g_debug("listen to monitor changed");
|
||||||
|
g_signal_connect(monitor_list, "items-changed", G_CALLBACK(class->monitor_changed_handle), shell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_gtk_app_active(GtkApplication *app, void *data)
|
||||||
|
{
|
||||||
|
(void)app;
|
||||||
|
DiyaShell *shell = data;
|
||||||
|
DiyaShellClass *class = DIYA_SHELL_GET_CLASS(shell);
|
||||||
|
// DiyaShellPrivate *priv = diya_shell_get_instance_private(shell);
|
||||||
|
/**
|
||||||
|
* TODO: read timeout from setting
|
||||||
|
*/
|
||||||
|
g_object_set(shell, DIYA_PROP_SHELL_IDLE_TIMEOUT, DEFAULT_IDLE_TIMEOUT, NULL);
|
||||||
|
|
||||||
|
if (class->active_handle)
|
||||||
|
{
|
||||||
|
class->active_handle(shell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean diya_shell_sigint_handle(gpointer data)
|
||||||
|
{
|
||||||
|
g_object_unref(DIYA_SHELL(data));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean diya_shell_sighub_handle(DiyaShell *self)
|
||||||
|
{
|
||||||
|
// reload css file
|
||||||
|
diya_shell_reload(self);
|
||||||
|
DiyaShellClass *class = DIYA_SHELL_GET_CLASS(self);
|
||||||
|
if (class->reload_handle)
|
||||||
|
{
|
||||||
|
class->reload_handle(self);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_gtk_application(DiyaShell *self)
|
||||||
|
{
|
||||||
|
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
|
||||||
|
if (priv->app)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
priv->app = gtk_application_new(priv->name, G_APPLICATION_DEFAULT_FLAGS);
|
||||||
|
g_signal_connect(priv->app, "startup", G_CALLBACK(on_gtk_app_startup), (void *)self);
|
||||||
|
g_signal_connect(priv->app, "activate", G_CALLBACK(on_gtk_app_active), (void *)self);
|
||||||
|
g_unix_signal_add(SIGINT, (GSourceFunc)diya_shell_sigint_handle, (void *)self);
|
||||||
|
g_unix_signal_add(SIGHUP, (GSourceFunc)diya_shell_sighub_handle, (void *)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void diya_shell_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
|
static void diya_shell_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
|
||||||
@ -41,9 +266,37 @@ static void diya_shell_set_property(GObject *object, guint property_id, const GV
|
|||||||
|
|
||||||
switch (property_id)
|
switch (property_id)
|
||||||
{
|
{
|
||||||
case PROP_SHELL_WAYLAND:
|
case PROP_SHELL_NAME:
|
||||||
priv->wayland = g_value_get_pointer(value);
|
if (priv->name)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
priv->name = g_strdup(g_value_get_string(value));
|
||||||
|
init_gtk_application(self);
|
||||||
break;
|
break;
|
||||||
|
case PROP_SHELL_IDLE_TO:
|
||||||
|
if(priv->idle_notif)
|
||||||
|
{
|
||||||
|
g_object_unref(priv->idle_notif);
|
||||||
|
}
|
||||||
|
priv->idle_notif = diya_shell_get_idle_notification(self, g_value_get_uint(value));
|
||||||
|
g_signal_connect(priv->idle_notif, DIYA_SIGNAL_IDLE_NOTIF_IDLE, G_CALLBACK(diya_shell_idle), self);
|
||||||
|
g_signal_connect(priv->idle_notif, DIYA_SIGNAL_IDLE_NOTIF_RESUME, G_CALLBACK(diya_shell_resume), self);
|
||||||
|
break;
|
||||||
|
case PROP_SHELL_THEME:
|
||||||
|
{
|
||||||
|
const gchar *theme = g_value_get_string(value);
|
||||||
|
if (!priv->theme || !g_str_equal(priv->theme, theme))
|
||||||
|
{
|
||||||
|
if (priv->theme)
|
||||||
|
{
|
||||||
|
g_free(priv->theme);
|
||||||
|
}
|
||||||
|
priv->theme = g_strdup(theme);
|
||||||
|
diya_shell_reload_theme(self);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -59,37 +312,351 @@ static void diya_shell_get_property(GObject *object, guint property_id, GValue *
|
|||||||
case PROP_SHELL_WAYLAND:
|
case PROP_SHELL_WAYLAND:
|
||||||
g_value_set_pointer(value, priv->wayland);
|
g_value_set_pointer(value, priv->wayland);
|
||||||
break;
|
break;
|
||||||
|
case PROP_SHELL_APP:
|
||||||
|
g_value_set_pointer(value, priv->app);
|
||||||
|
break;
|
||||||
|
case PROP_SHELL_NAME:
|
||||||
|
g_value_set_string(value, priv->name);
|
||||||
|
break;
|
||||||
|
case PROP_SHELL_THEME:
|
||||||
|
g_value_set_string(value, priv->theme);
|
||||||
|
break;
|
||||||
|
case PROP_SHELL_IDLE_TO:
|
||||||
|
if(priv->idle_notif)
|
||||||
|
{
|
||||||
|
g_value_set_uint(value, diya_idle_notification_get_timeout(priv->idle_notif));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_value_set_uint(value, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void diya_shell_init(DiyaShell *self)
|
static void diya_shell_init(DiyaShell *self)
|
||||||
{
|
{
|
||||||
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
|
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
|
||||||
priv->wayland = NULL;
|
priv->wayland = NULL;
|
||||||
|
priv->app = NULL;
|
||||||
|
priv->name = NULL;
|
||||||
|
priv->vkbs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref);
|
||||||
|
priv->css_provider = NULL;
|
||||||
|
priv->input = NULL;
|
||||||
|
priv->files_watchdog = NULL;
|
||||||
|
priv->theme = NULL;
|
||||||
|
priv->idle_notif = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
DiyaWayland *diya_shell_get_wayland(DiyaShell *shell)
|
DiyaWayland *diya_shell_get_wayland(DiyaShell *shell)
|
||||||
{
|
{
|
||||||
DiyaWayland * wayland;
|
DiyaShellPrivate *priv = diya_shell_get_instance_private(shell);
|
||||||
g_object_get(shell,"wayland", &wayland, NULL);
|
assert(DIYA_IS_WAYLAND(priv->wayland));
|
||||||
assert(DIYA_IS_WAYLAND(wayland));
|
return priv->wayland;
|
||||||
return wayland;
|
}
|
||||||
|
|
||||||
|
GtkApplication *diya_shell_get_application(DiyaShell *shell)
|
||||||
|
{
|
||||||
|
DiyaShellPrivate *priv = diya_shell_get_instance_private(shell);
|
||||||
|
assert(GTK_IS_APPLICATION(priv->app));
|
||||||
|
return priv->app;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *diya_shell_get_name(DiyaShell *shell)
|
||||||
|
{
|
||||||
|
DiyaShellPrivate *priv = diya_shell_get_instance_private(shell);
|
||||||
|
return priv->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar *diya_shell_to_string(DiyaObject *object)
|
||||||
|
{
|
||||||
|
return diya_shell_get_name(DIYA_SHELL(object));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void diya_shell_class_init(DiyaShellClass *class)
|
static void diya_shell_class_init(DiyaShellClass *class)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
gobject_class->dispose = diya_shell_dispose;
|
gobject_class->dispose = diya_shell_dispose;
|
||||||
|
gobject_class->finalize = diya_shell_finalize;
|
||||||
gobject_class->set_property = diya_shell_set_property;
|
gobject_class->set_property = diya_shell_set_property;
|
||||||
gobject_class->get_property = diya_shell_get_property;
|
gobject_class->get_property = diya_shell_get_property;
|
||||||
|
|
||||||
|
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
||||||
|
base_class->to_string = diya_shell_to_string;
|
||||||
|
|
||||||
class->foreign_register = NULL;
|
class->foreign_register = NULL;
|
||||||
class->virtual_keyboard_register = diya_virtual_keyboard_register;
|
class->virtual_keyboard_register = diya_virtual_keyboard_register;
|
||||||
|
class->monitor_changed_handle = NULL;
|
||||||
|
class->startup_handle = NULL;
|
||||||
|
class->active_handle = NULL;
|
||||||
|
class->reload_handle = NULL;
|
||||||
|
|
||||||
|
shell_properties[PROP_SHELL_WAYLAND] = g_param_spec_pointer(DIYA_PROP_SHELL_WAYLAND, NULL, "Shell wayland", G_PARAM_READABLE); //
|
||||||
|
shell_properties[PROP_SHELL_NAME] = g_param_spec_string(DIYA_PROP_SHELL_NAME, NULL, "Shell name", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||||
|
shell_properties[PROP_SHELL_APP] = g_param_spec_pointer(DIYA_PROP_SHELL_APPLICATION, NULL, "Shell application", G_PARAM_READABLE);
|
||||||
|
shell_properties[PROP_SHELL_THEME] = g_param_spec_string(DIYA_PROP_SHELL_THEME, NULL, "Shell theme", NULL, G_PARAM_READWRITE);
|
||||||
|
shell_properties[PROP_SHELL_IDLE_TO] = g_param_spec_uint(DIYA_PROP_SHELL_IDLE_TIMEOUT, NULL, "Shell IDLE timeout", 0, UINT32_MAX ,DEFAULT_IDLE_TIMEOUT, G_PARAM_READWRITE);
|
||||||
|
|
||||||
shell_properties[PROP_SHELL_WAYLAND] = g_param_spec_pointer("wayland", NULL, "Shell wayland", G_PARAM_READWRITE); //
|
|
||||||
g_object_class_install_properties(gobject_class, N_PROPERTIES, shell_properties);
|
g_object_class_install_properties(gobject_class, N_PROPERTIES, shell_properties);
|
||||||
|
|
||||||
|
// define signals
|
||||||
|
g_signal_new(DIYA_SIGNAL_SHELL_KEYBOARD_ENTER,
|
||||||
|
DIYA_TYPE_SHELL,
|
||||||
|
G_SIGNAL_DETAILED |
|
||||||
|
G_SIGNAL_ACTION |
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
3,
|
||||||
|
G_TYPE_POINTER,
|
||||||
|
G_TYPE_POINTER,
|
||||||
|
G_TYPE_POINTER);
|
||||||
|
g_signal_new(DIYA_SIGNAL_SHELL_KEYBOARD_MODIFIER_CHANGED,
|
||||||
|
DIYA_TYPE_SHELL,
|
||||||
|
G_SIGNAL_DETAILED |
|
||||||
|
G_SIGNAL_ACTION |
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
2,
|
||||||
|
G_TYPE_POINTER,
|
||||||
|
G_TYPE_POINTER);
|
||||||
|
g_signal_new(DIYA_SIGNAL_SHELL_KEYBOARD_LEAVE,
|
||||||
|
DIYA_TYPE_SHELL,
|
||||||
|
G_SIGNAL_DETAILED |
|
||||||
|
G_SIGNAL_ACTION |
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
0);
|
||||||
|
g_signal_new(DIYA_SIGNAL_SHELL_KEY_PRESSED,
|
||||||
|
DIYA_TYPE_SHELL,
|
||||||
|
G_SIGNAL_DETAILED |
|
||||||
|
G_SIGNAL_ACTION |
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
4,
|
||||||
|
G_TYPE_POINTER,
|
||||||
|
G_TYPE_POINTER,
|
||||||
|
G_TYPE_UINT,
|
||||||
|
G_TYPE_UINT);
|
||||||
|
|
||||||
|
g_signal_new(DIYA_SIGNAL_SHELL_KEY_RELEASED,
|
||||||
|
DIYA_TYPE_SHELL,
|
||||||
|
G_SIGNAL_DETAILED |
|
||||||
|
G_SIGNAL_ACTION |
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
4,
|
||||||
|
G_TYPE_POINTER,
|
||||||
|
G_TYPE_POINTER,
|
||||||
|
G_TYPE_UINT,
|
||||||
|
G_TYPE_UINT);
|
||||||
|
g_signal_new(DIYA_SIGNAL_SHELL_IDLE,
|
||||||
|
DIYA_TYPE_SHELL,
|
||||||
|
G_SIGNAL_DETAILED |
|
||||||
|
G_SIGNAL_ACTION |
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
0);
|
||||||
|
g_signal_new(DIYA_SIGNAL_SHELL_RESUME,
|
||||||
|
DIYA_TYPE_SHELL,
|
||||||
|
G_SIGNAL_DETAILED |
|
||||||
|
G_SIGNAL_ACTION |
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int diya_shell_handle_local_options(GApplication *application, GVariantDict *options, gpointer user_data)
|
||||||
|
{
|
||||||
|
(void)application;
|
||||||
|
(void)user_data;
|
||||||
|
#ifdef __SHELL_VERSION__
|
||||||
|
guint32 count;
|
||||||
|
if (g_variant_dict_lookup(options, "version", "b", &count))
|
||||||
|
{
|
||||||
|
g_print("Shell version: %s\n", __SHELL_VERSION__);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int diya_shell_run(DiyaShell *shell, int argc, char **argv)
|
||||||
|
{
|
||||||
|
DiyaShellPrivate *priv = diya_shell_get_instance_private(shell);
|
||||||
|
assert(GTK_IS_APPLICATION(priv->app));
|
||||||
|
GtkApplication *app = priv->app;
|
||||||
|
|
||||||
|
/*
|
||||||
|
// theme dir
|
||||||
|
gchar *path = g_strconcat(g_get_user_config_dir(), "/diya/themes/", NULL);
|
||||||
|
g_mkdir_with_parents((const gchar *)path, 0755);
|
||||||
|
g_free(path);
|
||||||
|
*/
|
||||||
|
|
||||||
|
// keymap dir
|
||||||
|
gchar *path = g_strconcat(g_get_user_config_dir(), "/diya/xkb/", NULL);
|
||||||
|
g_mkdir_with_parents((const gchar *)path, 0755);
|
||||||
|
g_free(path);
|
||||||
|
const GOptionEntry cmd_params[] =
|
||||||
|
{
|
||||||
|
#ifdef __SHELL_VERSION__
|
||||||
|
{
|
||||||
|
.long_name = "version",
|
||||||
|
.short_name = 'v',
|
||||||
|
.flags = G_OPTION_FLAG_NONE,
|
||||||
|
.arg = G_OPTION_ARG_NONE,
|
||||||
|
.arg_data = NULL,
|
||||||
|
.description = "Show version information",
|
||||||
|
.arg_description = NULL,
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
{NULL}};
|
||||||
|
g_application_add_main_option_entries(G_APPLICATION(app), cmd_params);
|
||||||
|
g_signal_connect(app, "handle-local-options", G_CALLBACK(diya_shell_handle_local_options), shell);
|
||||||
|
int status = g_application_run(G_APPLICATION(app), argc, argv);
|
||||||
|
g_object_unref(app);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
DiyaVirtualKeyboard *diya_shell_get_virtual_keyboard(DiyaShell *shell, const gchar *name)
|
||||||
|
{
|
||||||
|
DiyaVirtualKeyboard *vkb = NULL;
|
||||||
|
DiyaShellPrivate *priv = diya_shell_get_instance_private(shell);
|
||||||
|
if (name)
|
||||||
|
{
|
||||||
|
if (g_hash_table_contains(priv->vkbs, name))
|
||||||
|
{
|
||||||
|
g_debug("diya_shell_get_virtual_keyboard: Getting keyboard %s from cache", name);
|
||||||
|
vkb = g_hash_table_lookup(priv->vkbs, name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gchar *keymap_file = g_strconcat(g_get_user_config_dir(), "/diya/xkb/", name, ".keymap", NULL);
|
||||||
|
g_debug("diya_shell_get_virtual_keyboard: Looking for keymap file: %s", keymap_file);
|
||||||
|
if (g_file_test(keymap_file, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK))
|
||||||
|
{
|
||||||
|
vkb = diya_virtual_keyboard_new(shell, keymap_file);
|
||||||
|
if (vkb)
|
||||||
|
{
|
||||||
|
g_debug("diya_shell_get_virtual_keyboard: add new keyboard %s to cache", name);
|
||||||
|
g_hash_table_insert(priv->vkbs, (gpointer)g_strdup(name), vkb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(keymap_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vkb)
|
||||||
|
{
|
||||||
|
g_debug("Fallback to default virtual key board");
|
||||||
|
if (!g_hash_table_contains(priv->vkbs, "default"))
|
||||||
|
{
|
||||||
|
g_debug("Add new keyboard instance to cache");
|
||||||
|
g_hash_table_insert(priv->vkbs, (gpointer)g_strdup("default"), diya_virtual_keyboard_new(shell, NULL));
|
||||||
|
}
|
||||||
|
vkb = g_hash_table_lookup(priv->vkbs, "default");
|
||||||
|
}
|
||||||
|
|
||||||
|
return vkb;
|
||||||
|
}
|
||||||
|
void diya_shell_monitor_input(DiyaShell *self)
|
||||||
|
{
|
||||||
|
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
|
||||||
|
if (priv->input)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
priv->input = diya_input_new(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean diya_shell_watch_file(DiyaShell *self, const gchar *file, GCallback callback, gpointer userdata)
|
||||||
|
{
|
||||||
|
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
|
||||||
|
if (!priv->files_watchdog)
|
||||||
|
{
|
||||||
|
priv->files_watchdog = diya_files_monitor_new();
|
||||||
|
}
|
||||||
|
return diya_files_monitor_watch(priv->files_watchdog, file, callback, userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_shell_unwatch_file(DiyaShell *self, const gchar *file)
|
||||||
|
{
|
||||||
|
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
|
||||||
|
if (priv->files_watchdog)
|
||||||
|
{
|
||||||
|
diya_files_monitor_unwatch(priv->files_watchdog, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_shell_launch(DiyaShell *self, GAppInfo *app)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
|
||||||
|
GAppLaunchContext *context = g_app_launch_context_new();
|
||||||
|
if (priv->theme)
|
||||||
|
{
|
||||||
|
g_app_launch_context_setenv(context, "GTK_THEME", priv->theme);
|
||||||
|
}
|
||||||
|
g_app_info_launch(app, NULL, context, &error);
|
||||||
|
g_object_unref(context);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
g_critical("Unable to launch application: %s", error->message);
|
||||||
|
g_error_free(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_shell_power_display(DiyaShell* self, gboolean mode)
|
||||||
|
{
|
||||||
|
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
|
||||||
|
struct zwlr_output_power_manager_v1 * mngr = diya_wayland_get_output_mngr(priv->wayland);
|
||||||
|
if(!mngr)
|
||||||
|
{
|
||||||
|
g_warning("Output power manager protocol is not available");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GdkDisplay *display = gdk_display_get_default();
|
||||||
|
GListModel *monitors = gdk_display_get_monitors(display);
|
||||||
|
guint n_monitors = g_list_model_get_n_items(monitors);
|
||||||
|
|
||||||
|
for (guint i = 0; i < n_monitors; ++i)
|
||||||
|
{
|
||||||
|
GdkMonitor *monitor = g_list_model_get_item(monitors, i);
|
||||||
|
struct wl_output * output = gdk_wayland_monitor_get_wl_output(monitor);
|
||||||
|
struct zwlr_output_power_v1 * output_power = zwlr_output_power_manager_v1_get_output_power(mngr, output);
|
||||||
|
zwlr_output_power_v1_set_mode(output_power, mode? ZWLR_OUTPUT_POWER_V1_MODE_ON: ZWLR_OUTPUT_POWER_V1_MODE_OFF);
|
||||||
|
zwlr_output_power_v1_destroy(output_power);
|
||||||
|
}
|
||||||
}
|
}
|
44
src/shell.h
44
src/shell.h
@ -1,27 +1,57 @@
|
|||||||
#ifndef DIYA_SHELL_H
|
#ifndef DIYA_SHELL_H
|
||||||
#define DIYA_SHELL_H
|
#define DIYA_SHELL_H
|
||||||
#include <stdint.h>
|
#include <gio/gio.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
#include "base.h"
|
#include "base.h"
|
||||||
|
|
||||||
|
#define DIYA_ENV_THEME "DIYA_DEFAULT_THEME"
|
||||||
|
#define DIYA_ENV_VKB_KEYMAP "DIYA_VKB_KEYMAP"
|
||||||
|
|
||||||
|
#define DIYA_PROP_SHELL_WAYLAND "wayland"
|
||||||
|
#define DIYA_PROP_SHELL_NAME "name"
|
||||||
|
#define DIYA_PROP_SHELL_APPLICATION "application"
|
||||||
|
#define DIYA_PROP_SHELL_THEME "theme"
|
||||||
|
#define DIYA_PROP_SHELL_IDLE_TIMEOUT "idle-timeout"
|
||||||
|
|
||||||
|
|
||||||
|
#define DIYA_SIGNAL_SHELL_KEYBOARD_ENTER "keyboard-enter"
|
||||||
|
#define DIYA_SIGNAL_SHELL_KEYBOARD_LEAVE "keyboard-leave"
|
||||||
|
#define DIYA_SIGNAL_SHELL_KEY_PRESSED "key-pressed"
|
||||||
|
#define DIYA_SIGNAL_SHELL_KEY_RELEASED "key-released"
|
||||||
|
#define DIYA_SIGNAL_SHELL_KEYBOARD_MODIFIER_CHANGED "keyboard-modifier-changed"
|
||||||
|
#define DIYA_SIGNAL_SHELL_IDLE "idle"
|
||||||
|
#define DIYA_SIGNAL_SHELL_RESUME "resume"
|
||||||
|
|
||||||
#define DIYA_TYPE_SHELL (diya_shell_get_type())
|
#define DIYA_TYPE_SHELL (diya_shell_get_type())
|
||||||
G_DECLARE_DERIVABLE_TYPE(DiyaShell, diya_shell, DIYA, SHELL, DiyaObject)
|
G_DECLARE_DERIVABLE_TYPE(DiyaShell, diya_shell, DIYA, SHELL, DiyaObject)
|
||||||
|
|
||||||
#define DIYA_TYPE_WAYLAND (diya_wayland_get_type ())
|
|
||||||
G_DECLARE_FINAL_TYPE (DiyaWayland, diya_wayland, DIYA, WAYLAND, DiyaShellObject)
|
|
||||||
|
|
||||||
struct wl_registry;
|
struct wl_registry;
|
||||||
|
|
||||||
typedef void (*wl_protocol_manager_register_t)(struct wl_registry*, uint32_t,DiyaShell*);
|
typedef void (*wl_protocol_manager_register_t)(gpointer,DiyaShell*);
|
||||||
|
|
||||||
struct _DiyaShellClass
|
struct _DiyaShellClass
|
||||||
{
|
{
|
||||||
DiyaObjectClass parent_class;
|
DiyaObjectClass parent_class;
|
||||||
wl_protocol_manager_register_t foreign_register;
|
wl_protocol_manager_register_t foreign_register;
|
||||||
wl_protocol_manager_register_t virtual_keyboard_register;
|
wl_protocol_manager_register_t virtual_keyboard_register;
|
||||||
|
void (*monitor_changed_handle)(GListModel* /*list*/,guint /*position*/, guint /*removed*/,guint /*added*/, gpointer);
|
||||||
|
void (*startup_handle)(DiyaShell*);
|
||||||
|
void (*active_handle)(DiyaShell*);
|
||||||
|
void (*reload_handle)(DiyaShell*);
|
||||||
};
|
};
|
||||||
|
|
||||||
void diya_shell_wayland_init(DiyaShell *shell);
|
USE_CLASS(DiyaWayland);
|
||||||
|
USE_CLASS(DiyaVirtualKeyboard);
|
||||||
|
|
||||||
DiyaWayland * diya_shell_get_wayland(DiyaShell* shell);
|
DiyaWayland * diya_shell_get_wayland(DiyaShell* shell);
|
||||||
|
GtkApplication* diya_shell_get_application(DiyaShell* shell);
|
||||||
|
const char* diya_shell_get_name(DiyaShell* shell);
|
||||||
|
DiyaVirtualKeyboard* diya_shell_get_virtual_keyboard(DiyaShell* shell, const gchar* name);
|
||||||
|
void diya_shell_monitor_input(DiyaShell* shell);
|
||||||
|
gboolean diya_shell_watch_file(DiyaShell* shell, const gchar* file, GCallback callback, gpointer userdata);
|
||||||
|
void diya_shell_unwatch_file(DiyaShell* shell, const gchar* file);
|
||||||
|
void diya_shell_power_display(DiyaShell* shell, gboolean mode);
|
||||||
|
void diya_shell_launch(DiyaShell* shell, GAppInfo* app);
|
||||||
|
|
||||||
|
int diya_shell_run(DiyaShell* shell, int argc, char **argv);
|
||||||
#endif
|
#endif
|
@ -12,24 +12,169 @@
|
|||||||
#include "virtual-keyboard-unstable-v1.h"
|
#include "virtual-keyboard-unstable-v1.h"
|
||||||
#include "virtual-keyboard.h"
|
#include "virtual-keyboard.h"
|
||||||
#include "wayland.h"
|
#include "wayland.h"
|
||||||
|
#include "shell.h"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DIYA_VKB_KEY_MOD_NONE = 0,
|
||||||
|
DIYA_VKB_KEY_MOD_SHIFT = 1,
|
||||||
|
DIYA_VKB_KEY_MOD_CAPS_LOCK = 2,
|
||||||
|
DIYA_VKB_KEY_MOD_CTRL = 4,
|
||||||
|
DIYA_VKB_KEY_MOD_ALT = 8,
|
||||||
|
DIYA_VKB_KEY_MOD_SUPER = 64,
|
||||||
|
DIYA_VKB_KEY_MOD_ALT_GR = 128,
|
||||||
|
} diya_vkb_key_modifier_t;
|
||||||
|
|
||||||
|
|
||||||
|
struct _DiyaVkbKey
|
||||||
|
{
|
||||||
|
DiyaObject parent;
|
||||||
|
uint32_t code;
|
||||||
|
gchar *key_caps[3];
|
||||||
|
uint32_t syms[3];
|
||||||
|
gchar *info;
|
||||||
|
diya_vkb_key_modifier_t mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_FINAL_TYPE(DiyaVkbKey, diya_vkb_key, DIYA_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static void diya_vkb_key_finalize(GObject *object)
|
||||||
|
{
|
||||||
|
DiyaVkbKey *self = DIYA_VKB_KEY(object);
|
||||||
|
g_debug("diya_vkb_key_finalize: %s", diya_object_to_string(object));
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
if (self->key_caps[i])
|
||||||
|
{
|
||||||
|
free(self->key_caps[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self->code = 0;
|
||||||
|
if (self->info)
|
||||||
|
{
|
||||||
|
free(self->info);
|
||||||
|
self->info = NULL;
|
||||||
|
}
|
||||||
|
G_OBJECT_CLASS(diya_vkb_key_parent_class)->finalize(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_vkb_key_dispose(GObject *object)
|
||||||
|
{
|
||||||
|
// DiyaVkbKey *self = DIYA_VKB_KEY(object);
|
||||||
|
g_debug("diya_vkb_key_dispose: %s", diya_object_to_string(object));
|
||||||
|
G_OBJECT_CLASS(diya_vkb_key_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_vkb_key_init(DiyaVkbKey *self)
|
||||||
|
{
|
||||||
|
self->code = 0;
|
||||||
|
memset(self->key_caps, 0, sizeof(self->key_caps));
|
||||||
|
memset(self->syms, 0, sizeof(self->syms));
|
||||||
|
self->mode = DIYA_VKB_KEY_MOD_NONE;
|
||||||
|
self->info = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar *diya_vkb_key_to_string(DiyaObject *object)
|
||||||
|
{
|
||||||
|
DiyaVkbKey *self = DIYA_VKB_KEY(object);
|
||||||
|
if (!self->info && self->code != 0)
|
||||||
|
{
|
||||||
|
self->info = (char *)malloc(128);
|
||||||
|
g_snprintf(self->info, 128,
|
||||||
|
"DiyaVkbKey: %d (0x%.4x: %s, 0x%.4x: %s, 0x%.4x: %s)",
|
||||||
|
self->code,
|
||||||
|
self->syms[0],
|
||||||
|
self->key_caps[0],
|
||||||
|
self->syms[1],
|
||||||
|
self->key_caps[1],
|
||||||
|
self->syms[2],
|
||||||
|
self->key_caps[2]);
|
||||||
|
}
|
||||||
|
return self->info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_vkb_key_class_init(DiyaVkbKeyClass *class)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
|
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
||||||
|
|
||||||
|
gobject_class->dispose = diya_vkb_key_dispose;
|
||||||
|
gobject_class->finalize = diya_vkb_key_finalize;
|
||||||
|
// gobject_class->set_property = diya_lock_session_set_property;
|
||||||
|
// gobject_class->get_property = diya_lock_session_get_property;
|
||||||
|
base_class->to_string = diya_vkb_key_to_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gchar *diya_vkb_key_get_keycap(DiyaVkbKey *key, uint32_t shift_level)
|
||||||
|
{
|
||||||
|
if (shift_level > 2)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return key->key_caps[shift_level];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*uint32_t diya_vkb_key_get_code(DiyaVkbKey *key)
|
||||||
|
{
|
||||||
|
return key->code - 8;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
gboolean diya_vkb_key_is_alphabet(DiyaVkbKey* self)
|
||||||
|
{
|
||||||
|
return (self->syms[0] >= XKB_KEY_a && self->code <= XKB_KEY_Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean diya_vkb_key_is_modifier(DiyaVkbKey* self)
|
||||||
|
{
|
||||||
|
return self->mode != DIYA_VKB_KEY_MOD_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief DiyaVirtualKeyboard class: lowlevel wayland virtual keyboard handle
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
static struct zwp_virtual_keyboard_manager_v1 *g_virtual_keyboard_manager = NULL;
|
|
||||||
|
|
||||||
struct _DiyaVirtualKeyboard
|
struct _DiyaVirtualKeyboard
|
||||||
{
|
{
|
||||||
DiyaShellObject parent;
|
DiyaShellObject parent;
|
||||||
struct zwp_virtual_keyboard_v1 *keyboard;
|
struct zwp_virtual_keyboard_v1 *keyboard;
|
||||||
|
struct xkb_context *vkb_ctx;
|
||||||
|
struct xkb_keymap *vkb_keymap;
|
||||||
|
GHashTable * keys;
|
||||||
|
guint32 key_mods;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_FINAL_TYPE(DiyaVirtualKeyboard, diya_virtual_keyboard, DIYA_TYPE_SHELL_OBJECT);
|
G_DEFINE_FINAL_TYPE(DiyaVirtualKeyboard, diya_virtual_keyboard, DIYA_TYPE_SHELL_OBJECT);
|
||||||
|
|
||||||
static void diya_virtual_keyboard_dispose(GObject *object)
|
static void diya_virtual_keyboard_finalize(GObject *object)
|
||||||
{
|
{
|
||||||
DiyaVirtualKeyboard *self = DIYA_VIRTUAL_KEYBOARD(object);
|
DiyaVirtualKeyboard *self = DIYA_VIRTUAL_KEYBOARD(object);
|
||||||
g_debug("diya_virtual_keyboard_dispose");
|
g_debug("diya_virtual_keyboard_finalize: %s", diya_object_to_string(object));
|
||||||
|
g_hash_table_destroy(self->keys);
|
||||||
if (self->keyboard)
|
if (self->keyboard)
|
||||||
{
|
{
|
||||||
zwp_virtual_keyboard_v1_destroy(self->keyboard);
|
zwp_virtual_keyboard_v1_destroy(self->keyboard);
|
||||||
|
self->keyboard = NULL;
|
||||||
|
}
|
||||||
|
G_OBJECT_CLASS(diya_virtual_keyboard_parent_class)->finalize(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_virtual_keyboard_dispose(GObject *object)
|
||||||
|
{
|
||||||
|
DiyaVirtualKeyboard *self = DIYA_VIRTUAL_KEYBOARD(object);
|
||||||
|
g_debug("diya_virtual_keyboard_dispose: %s", diya_object_to_string(object));
|
||||||
|
if (self->vkb_keymap)
|
||||||
|
{
|
||||||
|
xkb_keymap_unref(self->vkb_keymap);
|
||||||
|
self->vkb_keymap = NULL;
|
||||||
|
}
|
||||||
|
if (self->vkb_ctx)
|
||||||
|
{
|
||||||
|
xkb_context_unref(self->vkb_ctx);
|
||||||
|
self->vkb_ctx = NULL;
|
||||||
}
|
}
|
||||||
G_OBJECT_CLASS(diya_virtual_keyboard_parent_class)->dispose(object);
|
G_OBJECT_CLASS(diya_virtual_keyboard_parent_class)->dispose(object);
|
||||||
}
|
}
|
||||||
@ -37,12 +182,20 @@ static void diya_virtual_keyboard_dispose(GObject *object)
|
|||||||
static void diya_virtual_keyboard_init(DiyaVirtualKeyboard *self)
|
static void diya_virtual_keyboard_init(DiyaVirtualKeyboard *self)
|
||||||
{
|
{
|
||||||
self->keyboard = NULL;
|
self->keyboard = NULL;
|
||||||
|
self->vkb_ctx = NULL;
|
||||||
|
self->vkb_keymap = NULL;
|
||||||
|
self->keys = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref);
|
||||||
|
self->key_mods = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const gchar *diya_virtual_keyboard_to_string(DiyaObject *object)
|
static const gchar *diya_virtual_keyboard_to_string(DiyaObject *object)
|
||||||
{
|
{
|
||||||
(void)object;
|
DiyaVirtualKeyboard* self = DIYA_VIRTUAL_KEYBOARD(object);
|
||||||
return "Diya virtual keyboard instance";
|
if(self->vkb_keymap)
|
||||||
|
{
|
||||||
|
return xkb_keymap_layout_get_name(self->vkb_keymap,0);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void diya_virtual_keyboard_class_init(DiyaVirtualKeyboardClass *class)
|
static void diya_virtual_keyboard_class_init(DiyaVirtualKeyboardClass *class)
|
||||||
@ -51,9 +204,22 @@ static void diya_virtual_keyboard_class_init(DiyaVirtualKeyboardClass *class)
|
|||||||
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
||||||
|
|
||||||
gobject_class->dispose = diya_virtual_keyboard_dispose;
|
gobject_class->dispose = diya_virtual_keyboard_dispose;
|
||||||
|
gobject_class->finalize = diya_virtual_keyboard_finalize;
|
||||||
// gobject_class->set_property = diya_lock_session_set_property;
|
// gobject_class->set_property = diya_lock_session_set_property;
|
||||||
// gobject_class->get_property = diya_lock_session_get_property;
|
// gobject_class->get_property = diya_lock_session_get_property;
|
||||||
base_class->to_string = diya_virtual_keyboard_to_string;
|
base_class->to_string = diya_virtual_keyboard_to_string;
|
||||||
|
g_signal_new(DIYA_SIGNAL_VKB_MODIFIER_CHANGED,
|
||||||
|
DIYA_TYPE_VIRTUAL_KEYBOARD,
|
||||||
|
G_SIGNAL_DETAILED |
|
||||||
|
G_SIGNAL_ACTION |
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -134,87 +300,282 @@ static int create_keymap_fd(off_t size)
|
|||||||
|
|
||||||
DiyaVirtualKeyboard *diya_virtual_keyboard_new(DiyaShell *shell, const gchar *keymap_file)
|
DiyaVirtualKeyboard *diya_virtual_keyboard_new(DiyaShell *shell, const gchar *keymap_file)
|
||||||
{
|
{
|
||||||
gchar *content = NULL;
|
struct xkb_context *vkb_ctx = NULL;
|
||||||
GError *error = NULL;
|
struct xkb_keymap *vkb_keymap = NULL;
|
||||||
GBytes *bytes = NULL;
|
|
||||||
gsize len = 0;
|
gsize len = 0;
|
||||||
|
vkb_ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
if (keymap_file)
|
if (!vkb_ctx)
|
||||||
{
|
{
|
||||||
g_file_get_contents(keymap_file, &content, &len, &error);
|
g_critical("diya_virtual_keyboard_new: Failed to create XKB context: %s", strerror(errno));
|
||||||
if (error != NULL)
|
|
||||||
{
|
|
||||||
g_critical("diya_virtual_keyboard_new: Unable to read file %s: %s", keymap_file, error->message);
|
|
||||||
g_error_free(error);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (keymap_file)
|
||||||
|
{
|
||||||
|
g_debug("diya_virtual_keyboard_new: Load keymap from file: %s", keymap_file);
|
||||||
|
FILE *fp = fopen(keymap_file, "r");
|
||||||
|
if (!fp)
|
||||||
|
{
|
||||||
|
g_critical("diya_virtual_keyboard_new: Failed to open file %s: %s", keymap_file, strerror(errno));
|
||||||
|
xkb_context_unref(vkb_ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
vkb_keymap = xkb_keymap_new_from_file(vkb_ctx, fp, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
fclose(fp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
GError *error = NULL;
|
||||||
g_warning("No keymap file specified. Loading default keymap from resource");
|
g_warning("No keymap file specified. Loading default keymap from resource");
|
||||||
GBytes *bytes = g_resources_lookup_data("/dev/iohub/diya/shell/default.keymap", 0, &error);
|
GBytes *bytes = g_resources_lookup_data("/dev/iohub/diya/shell/vkb/default.keymap", 0, &error);
|
||||||
if (error != NULL)
|
if (error != NULL)
|
||||||
{
|
{
|
||||||
g_critical("Unable to read keymap file from resource %s", error->message);
|
g_critical("Unable to read keymap file from resource %s", error->message);
|
||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
|
xkb_context_unref(vkb_ctx);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
content = (gchar*)g_bytes_get_data(bytes, &len);
|
vkb_keymap = xkb_keymap_new_from_string(vkb_ctx, (gchar *)g_bytes_get_data(bytes, &len), XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
g_bytes_unref(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vkb_keymap)
|
||||||
|
{
|
||||||
|
g_critical("diya_virtual_keyboard_new: Unable to load keymap: %s", strerror(errno));
|
||||||
|
xkb_context_unref(vkb_ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *content = xkb_keymap_get_as_string(vkb_keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
|
||||||
|
len = strlen(content);
|
||||||
|
if (!content)
|
||||||
|
{
|
||||||
|
g_critical("diya_virtual_keyboard_new: xkb_keymap_get_as_string: %s", strerror(errno));
|
||||||
|
xkb_keymap_unref(vkb_keymap);
|
||||||
|
xkb_context_unref(vkb_ctx);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fd = create_keymap_fd(len);
|
int fd = create_keymap_fd(len);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
{
|
{
|
||||||
g_critical("diya_virtual_keyboard_new: create temp file");
|
g_critical("diya_virtual_keyboard_new: create temp file");
|
||||||
if(bytes)
|
xkb_keymap_unref(vkb_keymap);
|
||||||
{
|
xkb_context_unref(vkb_ctx);
|
||||||
g_bytes_unref(bytes);
|
free(content);
|
||||||
content = NULL;
|
return NULL;
|
||||||
}
|
|
||||||
if(content)
|
|
||||||
{
|
|
||||||
g_free(content);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ptr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
void *ptr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
if (ptr == (void *)-1)
|
if (ptr == (void *)-1)
|
||||||
{
|
{
|
||||||
g_critical("diya_virtual_keyboard_new: error mmap: %s", strerror(errno));
|
g_critical("diya_virtual_keyboard_new: error mmap: %s", strerror(errno));
|
||||||
|
xkb_keymap_unref(vkb_keymap);
|
||||||
|
xkb_context_unref(vkb_ctx);
|
||||||
close(fd);
|
close(fd);
|
||||||
if(bytes)
|
free(content);
|
||||||
{
|
return NULL;
|
||||||
g_bytes_unref(bytes);
|
|
||||||
content = NULL;
|
|
||||||
}
|
}
|
||||||
if(content)
|
// g_debug("Using keymap configuration: \n%s", content);
|
||||||
{
|
|
||||||
g_free(content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy((char *)ptr, content);
|
strcpy((char *)ptr, content);
|
||||||
|
free(content);
|
||||||
|
|
||||||
DiyaVirtualKeyboard *vkb = g_object_new(DIYA_TYPE_VIRTUAL_KEYBOARD, "shell", shell, NULL);
|
DiyaVirtualKeyboard *vkb = g_object_new(DIYA_TYPE_VIRTUAL_KEYBOARD, "shell", shell, NULL);
|
||||||
|
vkb->vkb_ctx = vkb_ctx;
|
||||||
|
vkb->vkb_keymap = vkb_keymap;
|
||||||
DiyaWayland *wayland = diya_shell_get_wayland(shell);
|
DiyaWayland *wayland = diya_shell_get_wayland(shell);
|
||||||
struct wl_seat *seat = diya_wayland_get_seat(wayland);
|
struct wl_seat *seat = diya_wayland_get_seat(wayland);
|
||||||
vkb->keyboard = zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(g_virtual_keyboard_manager, seat);
|
struct zwp_virtual_keyboard_manager_v1* mngr = diya_wayland_get_virtual_keyboard_mngr(wayland);
|
||||||
|
if(!mngr)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
vkb->keyboard = zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(mngr, seat);
|
||||||
zwp_virtual_keyboard_v1_keymap(vkb->keyboard, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, fd, len);
|
zwp_virtual_keyboard_v1_keymap(vkb->keyboard, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, fd, len);
|
||||||
|
|
||||||
|
|
||||||
return vkb;
|
return vkb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void diya_virtual_keyboard_register(struct wl_registry *registry, uint32_t name, DiyaShell *shell)
|
void diya_virtual_keyboard_register(gpointer mngr, DiyaShell *shell)
|
||||||
{
|
{
|
||||||
(void) shell;
|
(void) shell;
|
||||||
g_virtual_keyboard_manager = wl_registry_bind(registry, name, &zwp_virtual_keyboard_manager_v1_interface, 1);
|
(void) mngr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void diya_virtual_keyboard_send_key(DiyaVirtualKeyboard *self, uint32_t key, diya_vkb_state_t state)
|
void diya_virtual_keyboard_send_key(DiyaVirtualKeyboard *self, DiyaVkbKey* key, diya_vkb_state_t state)
|
||||||
{
|
{
|
||||||
|
guint32 old_mods = self->key_mods;
|
||||||
GDateTime *now = g_date_time_new_now_local();
|
GDateTime *now = g_date_time_new_now_local();
|
||||||
uint32_t current_time_ms = g_date_time_get_microsecond(now) / 1000;
|
uint32_t current_time_ms = g_date_time_get_microsecond(now) / 1000;
|
||||||
g_date_time_unref(now);
|
g_date_time_unref(now);
|
||||||
zwp_virtual_keyboard_v1_key(self->keyboard, current_time_ms, key, (uint32_t)state);
|
zwp_virtual_keyboard_v1_key(self->keyboard, current_time_ms, key->code - 8, (uint32_t)state);
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case VKB_KEY_STATE_PRESSED:
|
||||||
|
switch (key->mode)
|
||||||
|
{
|
||||||
|
case DIYA_VKB_KEY_MOD_NONE:
|
||||||
|
break;
|
||||||
|
case DIYA_VKB_KEY_MOD_CAPS_LOCK:
|
||||||
|
self->key_mods = (self->key_mods & DIYA_VKB_KEY_MOD_CAPS_LOCK) ^ key->mode;
|
||||||
|
zwp_virtual_keyboard_v1_modifiers(self->keyboard,0,0,self->key_mods,0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
self->key_mods ^= key->mode;
|
||||||
|
zwp_virtual_keyboard_v1_modifiers(self->keyboard,0,self->key_mods,0,0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VKB_KEY_STATE_RELEASED:
|
||||||
|
switch (key->mode)
|
||||||
|
{
|
||||||
|
case DIYA_VKB_KEY_MOD_NONE:
|
||||||
|
if(self->key_mods)
|
||||||
|
{
|
||||||
|
self->key_mods = self->key_mods & DIYA_VKB_KEY_MOD_CAPS_LOCK;
|
||||||
|
zwp_virtual_keyboard_v1_modifiers(self->keyboard,0,0,self->key_mods,0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(old_mods != self->key_mods)
|
||||||
|
{
|
||||||
|
g_signal_emit_by_name(self,DIYA_SIGNAL_VKB_MODIFIER_CHANGED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_virtual_keyboard_init_level(DiyaVkbKey* key, const xkb_keysym_t sym, int level)
|
||||||
|
{
|
||||||
|
char buf[32];
|
||||||
|
key->syms[level] = sym;
|
||||||
|
diya_vkb_key_modifier_t mod = DIYA_VKB_KEY_MOD_NONE;
|
||||||
|
switch (sym)
|
||||||
|
{
|
||||||
|
case XKB_KEY_Escape:
|
||||||
|
g_snprintf(buf, sizeof(buf), "%s", "Esc");
|
||||||
|
break;
|
||||||
|
case XKB_KEY_BackSpace:
|
||||||
|
g_snprintf(buf, sizeof(buf), "%s", "⌫");
|
||||||
|
break;
|
||||||
|
case XKB_KEY_Tab:
|
||||||
|
g_snprintf(buf, sizeof(buf), "%s", "⇥");
|
||||||
|
break;
|
||||||
|
case XKB_KEY_Return:
|
||||||
|
g_snprintf(buf, sizeof(buf), "%s", "⏎");
|
||||||
|
break;
|
||||||
|
case XKB_KEY_Control_L:
|
||||||
|
g_snprintf(buf, sizeof(buf), "%s", "Ctrl");
|
||||||
|
mod = DIYA_VKB_KEY_MOD_CTRL;
|
||||||
|
break;
|
||||||
|
case XKB_KEY_Shift_L:
|
||||||
|
g_snprintf(buf, sizeof(buf), "%s", "⇧");
|
||||||
|
mod = DIYA_VKB_KEY_MOD_SHIFT;
|
||||||
|
break;
|
||||||
|
case XKB_KEY_Caps_Lock:
|
||||||
|
g_snprintf(buf, sizeof(buf), "%s", "⇪");
|
||||||
|
mod = DIYA_VKB_KEY_MOD_CAPS_LOCK;
|
||||||
|
break;
|
||||||
|
case XKB_KEY_Alt_L:
|
||||||
|
g_snprintf(buf, sizeof(buf), "%s", "⎇");
|
||||||
|
mod = DIYA_VKB_KEY_MOD_ALT;
|
||||||
|
break;
|
||||||
|
case XKB_KEY_Alt_R:
|
||||||
|
case XKB_KEY_ISO_Level3_Shift:
|
||||||
|
g_snprintf(buf, sizeof(buf), "%s", "⇮");
|
||||||
|
mod = DIYA_VKB_KEY_MOD_ALT_GR;
|
||||||
|
break;
|
||||||
|
case XKB_KEY_space:
|
||||||
|
g_snprintf(buf, sizeof(buf), "%s", "⎵");
|
||||||
|
break;
|
||||||
|
case XKB_KEY_Up:
|
||||||
|
g_snprintf(buf, sizeof(buf), "%s", "↑");
|
||||||
|
break;
|
||||||
|
case XKB_KEY_Down:
|
||||||
|
g_snprintf(buf, sizeof(buf), "%s", "↓");
|
||||||
|
break;
|
||||||
|
case XKB_KEY_Left:
|
||||||
|
g_snprintf(buf, sizeof(buf), "%s", "←");
|
||||||
|
break;
|
||||||
|
case XKB_KEY_Right:
|
||||||
|
g_snprintf(buf, sizeof(buf), "%s", "→");
|
||||||
|
break;
|
||||||
|
case XKB_KEY_function:
|
||||||
|
g_snprintf(buf, sizeof(buf), "%s", "Fn");
|
||||||
|
break;
|
||||||
|
case XKB_KEY_Meta_L:
|
||||||
|
g_snprintf(buf, sizeof(buf), "%s", "⌘");
|
||||||
|
break;
|
||||||
|
case XKB_KEY_Super_L:
|
||||||
|
g_snprintf(buf, sizeof(buf), "%s", "●");
|
||||||
|
if(level != 0)
|
||||||
|
{
|
||||||
|
key->syms[0] = sym;
|
||||||
|
key->syms[level] = 0;
|
||||||
|
}
|
||||||
|
mod = DIYA_VKB_KEY_MOD_SUPER;
|
||||||
|
break;
|
||||||
|
case XKB_KEY_dead_circumflex:
|
||||||
|
g_snprintf(buf, sizeof(buf), "%s", "^");
|
||||||
|
break;
|
||||||
|
case XKB_KEY_dead_diaeresis:
|
||||||
|
g_snprintf(buf, sizeof(buf), "%s", "¨");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (xkb_keysym_to_utf8(sym, buf, sizeof(buf)) == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(level == 0)
|
||||||
|
{
|
||||||
|
key->mode = mod;
|
||||||
|
}
|
||||||
|
if(sym == XKB_KEY_Super_L && level != 0)
|
||||||
|
{
|
||||||
|
if(key->key_caps[0])
|
||||||
|
{
|
||||||
|
free(key->key_caps[0]);
|
||||||
|
}
|
||||||
|
key->key_caps[0] = g_strdup(buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
key->key_caps[level] = g_strdup(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DiyaVkbKey *diya_virtual_keyboard_get_key(DiyaVirtualKeyboard *self, uint32_t code)
|
||||||
|
{
|
||||||
|
if(!g_hash_table_contains(self->keys, GUINT_TO_POINTER(code)))
|
||||||
|
{
|
||||||
|
DiyaVkbKey *key = g_object_new(DIYA_TYPE_VKB_KEY, NULL);
|
||||||
|
key->code = code;
|
||||||
|
int n_level = xkb_keymap_num_levels_for_key(self->vkb_keymap, code, 0);
|
||||||
|
if (n_level > 0)
|
||||||
|
{
|
||||||
|
n_level = n_level > 3 ? 3 : n_level;
|
||||||
|
for (int level = 0; level < n_level; level++)
|
||||||
|
{
|
||||||
|
const xkb_keysym_t *syms = NULL;
|
||||||
|
int n_sym = xkb_keymap_key_get_syms_by_level(self->vkb_keymap, code, 0, level, &syms);
|
||||||
|
if (n_sym <= 0 || syms[0] == key->syms[0] || syms[0] == key->syms[1])
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
diya_virtual_keyboard_init_level(key, syms[0],level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_hash_table_insert(self->keys, GUINT_TO_POINTER(code), key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_hash_table_lookup(self->keys, GUINT_TO_POINTER(code));
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean diya_virtual_keyboard_key_modifier_is_active(DiyaVirtualKeyboard* vkb, DiyaVkbKey* key)
|
||||||
|
{
|
||||||
|
return (key->mode & vkb->key_mods) > 0;
|
||||||
}
|
}
|
@ -1,7 +1,16 @@
|
|||||||
#ifndef DIYA_VIRTUAL_KEYBOARD_H
|
#ifndef DIYA_VIRTUAL_KEYBOARD_H
|
||||||
#define DIYA_VIRTUAL_KEYBOARD_H
|
#define DIYA_VIRTUAL_KEYBOARD_H
|
||||||
|
|
||||||
#include "shell.h"
|
#include "base.h"
|
||||||
|
|
||||||
|
#define DIYA_SIGNAL_VKB_MODIFIER_CHANGED "modifier-changed"
|
||||||
|
#define DIYA_SIGNAL_VKB_KEY_PRESSED "pressed"
|
||||||
|
#define DIYA_SIGNAL_VKB_KEY_RELEASED "released"
|
||||||
|
|
||||||
|
#define DIYA_TYPE_VIRTUAL_KEYBOARD (diya_virtual_keyboard_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (DiyaVirtualKeyboard, diya_virtual_keyboard, DIYA, VIRTUAL_KEYBOARD, DiyaShellObject)
|
||||||
|
|
||||||
|
USE_CLASS(DiyaShell);
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
@ -9,11 +18,17 @@ typedef enum
|
|||||||
VKB_KEY_STATE_PRESSED = 1 /*WL_KEYBOARD_KEY_STATE_PRESSED*/,
|
VKB_KEY_STATE_PRESSED = 1 /*WL_KEYBOARD_KEY_STATE_PRESSED*/,
|
||||||
} diya_vkb_state_t;
|
} diya_vkb_state_t;
|
||||||
|
|
||||||
#define DIYA_TYPE_VIRTUAL_KEYBOARD (diya_virtual_keyboard_get_type ())
|
#define DIYA_TYPE_VKB_KEY (diya_vkb_key_get_type ())
|
||||||
G_DECLARE_FINAL_TYPE (DiyaVirtualKeyboard, diya_virtual_keyboard, DIYA, VIRTUAL_KEYBOARD, DiyaShellObject)
|
G_DECLARE_FINAL_TYPE (DiyaVkbKey, diya_vkb_key, DIYA, VKB_KEY, DiyaObject)
|
||||||
|
const gchar* diya_vkb_key_get_keycap(DiyaVkbKey* key, uint32_t shift_level);
|
||||||
|
gboolean diya_vkb_key_is_alphabet(DiyaVkbKey* key);
|
||||||
|
gboolean diya_vkb_key_is_modifier(DiyaVkbKey* key);
|
||||||
|
|
||||||
DiyaVirtualKeyboard* diya_virtual_keyboard_new(DiyaShell* shell, const gchar* keymap_file);
|
DiyaVirtualKeyboard* diya_virtual_keyboard_new(DiyaShell* shell, const gchar* keymap_file);
|
||||||
|
|
||||||
void diya_virtual_keyboard_register(struct wl_registry *registry, uint32_t name, DiyaShell *shell);
|
void diya_virtual_keyboard_register(gpointer mngr, DiyaShell *shell);
|
||||||
void diya_virtual_keyboard_send_key(DiyaVirtualKeyboard* vkb, uint32_t key, diya_vkb_state_t state);
|
void diya_virtual_keyboard_send_key(DiyaVirtualKeyboard* vkb, DiyaVkbKey* key, diya_vkb_state_t state);
|
||||||
|
|
||||||
|
DiyaVkbKey* diya_virtual_keyboard_get_key(DiyaVirtualKeyboard* vkb, uint32_t key);
|
||||||
|
gboolean diya_virtual_keyboard_key_modifier_is_active(DiyaVirtualKeyboard* vkb, DiyaVkbKey* key);
|
||||||
#endif
|
#endif
|
111
src/wayland.c
111
src/wayland.c
@ -3,8 +3,10 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "wlr-foreign-toplevel-management-unstable-v1.h"
|
#include "wlr-foreign-toplevel-management-unstable-v1.h"
|
||||||
#include "virtual-keyboard-unstable-v1.h"
|
#include "virtual-keyboard-unstable-v1.h"
|
||||||
|
#include "ext-idle-notify-v1.h"
|
||||||
|
#include "wlr-output-power-management-unstable-v1.h"
|
||||||
#include "wayland.h"
|
#include "wayland.h"
|
||||||
|
#include "shell.h"
|
||||||
|
|
||||||
struct _DiyaWayland
|
struct _DiyaWayland
|
||||||
{
|
{
|
||||||
@ -12,9 +14,42 @@ struct _DiyaWayland
|
|||||||
struct wl_compositor * compositor;
|
struct wl_compositor * compositor;
|
||||||
struct wl_shm * shm;
|
struct wl_shm * shm;
|
||||||
struct wl_seat * seat;
|
struct wl_seat * seat;
|
||||||
|
// protocol manager
|
||||||
|
struct zwlr_foreign_toplevel_manager_v1 * foreign_toplevel_mngr;
|
||||||
|
struct zwp_virtual_keyboard_manager_v1 * virtual_keyboard_mngr;
|
||||||
|
struct ext_idle_notifier_v1 * idle_notifier_mngr;
|
||||||
|
struct zwlr_output_power_manager_v1 * zwlr_output_power_manager_v1;
|
||||||
};
|
};
|
||||||
G_DEFINE_FINAL_TYPE(DiyaWayland, diya_wayland, DIYA_TYPE_SHELL_OBJECT)
|
G_DEFINE_FINAL_TYPE(DiyaWayland, diya_wayland, DIYA_TYPE_SHELL_OBJECT)
|
||||||
|
|
||||||
|
static void diya_wayland_finalize(GObject* object)
|
||||||
|
{
|
||||||
|
(void) object;
|
||||||
|
DiyaWayland * self = DIYA_WAYLAND(object);
|
||||||
|
if(self->foreign_toplevel_mngr)
|
||||||
|
{
|
||||||
|
zwlr_foreign_toplevel_manager_v1_destroy(self->foreign_toplevel_mngr);
|
||||||
|
self->foreign_toplevel_mngr = NULL;
|
||||||
|
}
|
||||||
|
if(self->virtual_keyboard_mngr)
|
||||||
|
{
|
||||||
|
zwp_virtual_keyboard_manager_v1_destroy(self->virtual_keyboard_mngr);
|
||||||
|
self->virtual_keyboard_mngr = NULL;
|
||||||
|
}
|
||||||
|
if(self->idle_notifier_mngr)
|
||||||
|
{
|
||||||
|
ext_idle_notifier_v1_destroy(self->idle_notifier_mngr);
|
||||||
|
self->idle_notifier_mngr = NULL;
|
||||||
|
}
|
||||||
|
if(self->zwlr_output_power_manager_v1)
|
||||||
|
{
|
||||||
|
zwlr_output_power_manager_v1_destroy(self->zwlr_output_power_manager_v1);
|
||||||
|
self->zwlr_output_power_manager_v1 = NULL;
|
||||||
|
}
|
||||||
|
g_debug("diya_wayland_finalize: %s", diya_object_to_string(object));
|
||||||
|
G_OBJECT_CLASS(diya_wayland_parent_class)->finalize(object);
|
||||||
|
}
|
||||||
|
|
||||||
static void diya_wayland_dispose(GObject* object)
|
static void diya_wayland_dispose(GObject* object)
|
||||||
{
|
{
|
||||||
(void) object;
|
(void) object;
|
||||||
@ -28,6 +63,10 @@ static void diya_wayland_init(DiyaWayland * self)
|
|||||||
self->compositor = NULL;
|
self->compositor = NULL;
|
||||||
self->shm = NULL;
|
self->shm = NULL;
|
||||||
self->seat = NULL;
|
self->seat = NULL;
|
||||||
|
self->foreign_toplevel_mngr = NULL;
|
||||||
|
self->virtual_keyboard_mngr = NULL;
|
||||||
|
self->idle_notifier_mngr = NULL;
|
||||||
|
self->zwlr_output_power_manager_v1 = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const gchar* diya_wayland_to_string(DiyaObject* object)
|
static const gchar* diya_wayland_to_string(DiyaObject* object)
|
||||||
@ -42,6 +81,7 @@ static void diya_wayland_class_init(DiyaWaylandClass *class)
|
|||||||
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
||||||
|
|
||||||
gobject_class->dispose = diya_wayland_dispose;
|
gobject_class->dispose = diya_wayland_dispose;
|
||||||
|
gobject_class->finalize = diya_wayland_finalize;
|
||||||
//gobject_class->set_property = diya_lock_session_set_property;
|
//gobject_class->set_property = diya_lock_session_set_property;
|
||||||
//gobject_class->get_property = diya_lock_session_get_property;
|
//gobject_class->get_property = diya_lock_session_get_property;
|
||||||
base_class->to_string = diya_wayland_to_string;
|
base_class->to_string = diya_wayland_to_string;
|
||||||
@ -60,29 +100,32 @@ static void handle_global(void *data, struct wl_registry *registry, uint32_t nam
|
|||||||
foreign_toplevel_register(registry,name);
|
foreign_toplevel_register(registry,name);
|
||||||
*/
|
*/
|
||||||
(void) version;
|
(void) version;
|
||||||
DiyaShell * shell = data;
|
DiyaWayland *wayland = data;
|
||||||
DiyaShellClass * class = DIYA_SHELL_GET_CLASS(shell);
|
DiyaShell * shell = diya_shell_object_get_shell(data);
|
||||||
DiyaWayland * wayland;
|
|
||||||
g_object_get(shell, "wayland", &wayland, NULL);
|
|
||||||
assert(DIYA_IS_WAYLAND(wayland));
|
|
||||||
g_debug("WAYLAND GLOBAL: %s", interface);
|
|
||||||
|
|
||||||
if (g_strcmp0(interface, zwlr_foreign_toplevel_manager_v1_interface.name) == 0)
|
assert(DIYA_IS_WAYLAND(wayland));
|
||||||
|
assert(DIYA_IS_SHELL(shell));
|
||||||
|
|
||||||
|
DiyaShellClass * class = DIYA_SHELL_GET_CLASS(shell);
|
||||||
|
g_debug("WAYLAND GLOBAL: %s", interface);
|
||||||
|
if (!wayland->foreign_toplevel_mngr && g_strcmp0(interface, zwlr_foreign_toplevel_manager_v1_interface.name) == 0)
|
||||||
{
|
{
|
||||||
if(class->foreign_register)
|
if(class->foreign_register)
|
||||||
{
|
{
|
||||||
//diya_session_shell_foreign_toplevel_register(registry, name, data);
|
//diya_session_shell_foreign_toplevel_register(registry, name, data);
|
||||||
g_debug("Wayland: register shell foreign top level manager");
|
g_debug("Wayland: register shell foreign top level manager");
|
||||||
class->foreign_register(registry, name, data);
|
wayland->foreign_toplevel_mngr = wl_registry_bind(registry, name, &zwlr_foreign_toplevel_manager_v1_interface, 3);
|
||||||
|
class->foreign_register(wayland->foreign_toplevel_mngr, shell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (g_strcmp0(interface, zwp_virtual_keyboard_manager_v1_interface.name) == 0)
|
if (!wayland->virtual_keyboard_mngr && g_strcmp0(interface, zwp_virtual_keyboard_manager_v1_interface.name) == 0)
|
||||||
{
|
{
|
||||||
if(class->virtual_keyboard_register)
|
if(class->virtual_keyboard_register)
|
||||||
{
|
{
|
||||||
//diya_session_shell_foreign_toplevel_register(registry, name, data);
|
//diya_session_shell_foreign_toplevel_register(registry, name, data);
|
||||||
g_debug("Wayland: register virtual keyboard manager");
|
g_debug("Wayland: register virtual keyboard manager");
|
||||||
class->virtual_keyboard_register(registry, name, data);
|
wayland->virtual_keyboard_mngr = wl_registry_bind(registry, name, &zwp_virtual_keyboard_manager_v1_interface, 1);
|
||||||
|
class->virtual_keyboard_register(wayland->virtual_keyboard_mngr, shell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -91,22 +134,32 @@ static void handle_global(void *data, struct wl_registry *registry, uint32_t nam
|
|||||||
diya_session_shell_session_lock_register(registry, name);
|
diya_session_shell_session_lock_register(registry, name);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
else if (strcmp(interface, wl_compositor_interface.name) == 0)
|
else if (!wayland->compositor && g_strcmp0(interface, wl_compositor_interface.name) == 0)
|
||||||
{
|
{
|
||||||
wayland->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 4);
|
wayland->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 4);
|
||||||
}
|
}
|
||||||
else if (strcmp(interface, wl_shm_interface.name) == 0)
|
else if (!wayland->shm && g_strcmp0(interface, wl_shm_interface.name) == 0)
|
||||||
{
|
{
|
||||||
wayland->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
|
wayland->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
|
||||||
}
|
}
|
||||||
else if (strcmp(interface, wl_seat_interface.name) == 0)
|
else if (!wayland->seat && g_strcmp0(interface, wl_seat_interface.name) == 0)
|
||||||
{
|
{
|
||||||
wayland->seat = wl_registry_bind(registry, name, &wl_seat_interface, 7);
|
wayland->seat = wl_registry_bind(registry, name, &wl_seat_interface, 7);
|
||||||
}
|
}
|
||||||
|
else if(!wayland->idle_notifier_mngr && g_strcmp0(interface, ext_idle_notifier_v1_interface.name) == 0)
|
||||||
|
{
|
||||||
|
g_debug("Wayland: register ext_idle_notifier_v1_interface");
|
||||||
|
wayland->idle_notifier_mngr = wl_registry_bind(registry, name, &ext_idle_notifier_v1_interface, 1);;
|
||||||
|
}
|
||||||
|
else if (!wayland->zwlr_output_power_manager_v1 && g_strcmp0(interface, zwlr_output_power_manager_v1_interface.name) == 0)
|
||||||
|
{
|
||||||
|
g_debug("Wayland: register zwlr_output_power_manager_v1_interface");
|
||||||
|
wayland->zwlr_output_power_manager_v1 = wl_registry_bind(registry, name, &zwlr_output_power_manager_v1_interface, 1);
|
||||||
|
//class->power_manager_register(wayland->zwlr_output_power_manager_v1, shell);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_global_remove(void *data, struct wl_registry *registry,
|
static void handle_global_remove(void *data, struct wl_registry *registry,uint32_t name)
|
||||||
uint32_t name)
|
|
||||||
{
|
{
|
||||||
(void) data;
|
(void) data;
|
||||||
(void) registry;
|
(void) registry;
|
||||||
@ -119,7 +172,7 @@ static const struct wl_registry_listener registry_listener =
|
|||||||
.global_remove = handle_global_remove
|
.global_remove = handle_global_remove
|
||||||
};
|
};
|
||||||
|
|
||||||
void diya_shell_wayland_init(DiyaShell *shell)
|
DiyaWayland* diya_wayland_new(DiyaShell *shell)
|
||||||
{
|
{
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
struct wl_registry *registry;
|
struct wl_registry *registry;
|
||||||
@ -127,20 +180,19 @@ void diya_shell_wayland_init(DiyaShell *shell)
|
|||||||
if (!display)
|
if (!display)
|
||||||
{
|
{
|
||||||
g_error("Can't get wayland display");
|
g_error("Can't get wayland display");
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
DiyaWayland * wayland = g_object_new(DIYA_TYPE_WAYLAND, "shell", shell, NULL);
|
DiyaWayland * wayland = g_object_new(DIYA_TYPE_WAYLAND, "shell", shell, NULL);
|
||||||
g_object_set(shell, "wayland", wayland, NULL);
|
|
||||||
//g_object_set(wayland, "shell", shell, NULL);
|
|
||||||
registry = wl_display_get_registry(display);
|
registry = wl_display_get_registry(display);
|
||||||
wl_registry_add_listener(registry, ®istry_listener, (void*)shell);
|
wl_registry_add_listener(registry, ®istry_listener, (void*)wayland);
|
||||||
wl_display_roundtrip(display);
|
// wl_display_roundtrip(display);
|
||||||
// wayland_monitor_probe();
|
// wayland_monitor_probe();
|
||||||
// GdkMonitor *mon = wayland_monitor_get_default();
|
// GdkMonitor *mon = wayland_monitor_get_default();
|
||||||
// g_info("default output: %s", (gchar *)g_object_get_data(G_OBJECT(mon), "xdg_name"));
|
// g_info("default output: %s", (gchar *)g_object_get_data(G_OBJECT(mon), "xdg_name"));
|
||||||
|
|
||||||
// wl_display_roundtrip(display);
|
// wl_display_roundtrip(display);
|
||||||
//wl_display_roundtrip(display);
|
//wl_display_roundtrip(display);
|
||||||
|
return wayland;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wl_surface* diya_wayland_create_surface(DiyaWayland * self)
|
struct wl_surface* diya_wayland_create_surface(DiyaWayland * self)
|
||||||
@ -178,3 +230,18 @@ struct wl_seat* diya_wayland_get_seat(DiyaWayland* self)
|
|||||||
assert(self->seat);
|
assert(self->seat);
|
||||||
return self->seat;
|
return self->seat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct zwp_virtual_keyboard_manager_v1* diya_wayland_get_virtual_keyboard_mngr(DiyaWayland* self)
|
||||||
|
{
|
||||||
|
return self->virtual_keyboard_mngr;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ext_idle_notifier_v1* diya_wayland_get_idle_mngr(DiyaWayland* self)
|
||||||
|
{
|
||||||
|
return self->idle_notifier_mngr;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct zwlr_output_power_manager_v1 * diya_wayland_get_output_mngr(DiyaWayland* self)
|
||||||
|
{
|
||||||
|
return self->zwlr_output_power_manager_v1;
|
||||||
|
}
|
@ -1,10 +1,19 @@
|
|||||||
#ifndef DIYA_SHELL_WAYLAND_H
|
#ifndef DIYA_SHELL_WAYLAND_H
|
||||||
#define DIYA_SHELL_WAYLAND_H
|
#define DIYA_SHELL_WAYLAND_H
|
||||||
|
|
||||||
#include "shell.h"
|
#include "base.h"
|
||||||
|
|
||||||
|
USE_CLASS(DiyaShell);
|
||||||
|
|
||||||
|
#define DIYA_TYPE_WAYLAND (diya_wayland_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (DiyaWayland, diya_wayland, DIYA, WAYLAND, DiyaShellObject)
|
||||||
|
|
||||||
struct wl_surface* diya_wayland_create_surface(DiyaWayland * self);
|
struct wl_surface* diya_wayland_create_surface(DiyaWayland * self);
|
||||||
struct wl_output* diya_wayland_get_output(DiyaWayland * self, int index);
|
struct wl_output* diya_wayland_get_output(DiyaWayland * self, int index);
|
||||||
struct wl_shm_pool * diya_wayland_create_shm_pool(DiyaWayland * self, int fd, guint size);
|
struct wl_shm_pool * diya_wayland_create_shm_pool(DiyaWayland * self, int fd, guint size);
|
||||||
struct wl_seat* diya_wayland_get_seat(DiyaWayland* self);
|
struct wl_seat* diya_wayland_get_seat(DiyaWayland* self);
|
||||||
|
struct zwp_virtual_keyboard_manager_v1* diya_wayland_get_virtual_keyboard_mngr(DiyaWayland* self);
|
||||||
|
struct ext_idle_notifier_v1* diya_wayland_get_idle_mngr(DiyaWayland* self);
|
||||||
|
struct zwlr_output_power_manager_v1 * diya_wayland_get_output_mngr(DiyaWayland* self);
|
||||||
|
DiyaWayland* diya_wayland_new(DiyaShell *shell);
|
||||||
#endif
|
#endif
|
106
src/widgets/base-widgets.c
Normal file
106
src/widgets/base-widgets.c
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
|
||||||
|
#include "base-widgets.h"
|
||||||
|
#include "shell.h"
|
||||||
|
/**
|
||||||
|
* @brief Implementation of DiyaShellWindow
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SW_NO_PROP,
|
||||||
|
SW_SHELL,
|
||||||
|
SW_N_PROPERTIES
|
||||||
|
};
|
||||||
|
|
||||||
|
static GParamSpec *g_sw_prop[SW_N_PROPERTIES] = {0};
|
||||||
|
|
||||||
|
typedef struct _DiyaShellWindowPrivate
|
||||||
|
{
|
||||||
|
GtkApplicationWindow parent;
|
||||||
|
DiyaShell * shell;
|
||||||
|
} DiyaShellWindowPrivate;
|
||||||
|
G_DEFINE_TYPE_WITH_PRIVATE(DiyaShellWindow, diya_shell_window, GTK_TYPE_APPLICATION_WINDOW)
|
||||||
|
|
||||||
|
static void diya_shell_window_dispose(GObject* object)
|
||||||
|
{
|
||||||
|
g_debug("diya_shell_window_dispose");
|
||||||
|
G_OBJECT_CLASS(diya_shell_window_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_shell_window_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
DiyaShellWindow * self = DIYA_SHELL_WINDOW(object);
|
||||||
|
DiyaShellWindowPrivate* priv = diya_shell_window_get_instance_private(self);
|
||||||
|
|
||||||
|
switch (property_id)
|
||||||
|
{
|
||||||
|
case SW_SHELL:
|
||||||
|
priv->shell = g_value_get_pointer(value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_shell_window_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
DiyaShellWindow * self = DIYA_SHELL_WINDOW(object);
|
||||||
|
DiyaShellWindowPrivate* priv = diya_shell_window_get_instance_private(self);
|
||||||
|
switch (property_id)
|
||||||
|
{
|
||||||
|
case SW_SHELL:
|
||||||
|
g_value_set_pointer(value, priv->shell);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void diya_shell_window_init(DiyaShellWindow *self)
|
||||||
|
{
|
||||||
|
DiyaShellWindowPrivate* priv = diya_shell_window_get_instance_private(self);
|
||||||
|
priv->shell = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_shell_window_class_init(DiyaShellWindowClass *class)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
|
gobject_class->dispose = diya_shell_window_dispose;
|
||||||
|
gobject_class->set_property = diya_shell_window_set_property;
|
||||||
|
gobject_class->get_property = diya_shell_window_get_property;
|
||||||
|
|
||||||
|
class->setup = NULL;
|
||||||
|
|
||||||
|
g_sw_prop[SW_SHELL] = g_param_spec_pointer(DIYA_PROP_SHELL, NULL, "Reference to global shell", G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY); //
|
||||||
|
|
||||||
|
g_object_class_install_properties (gobject_class, SW_N_PROPERTIES, g_sw_prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DiyaShellWindow* diya_shell_window_new(GType window_type, gpointer data)
|
||||||
|
{
|
||||||
|
DiyaShell* shell = data;
|
||||||
|
assert(shell);
|
||||||
|
GtkApplication * app;
|
||||||
|
g_object_get(shell, DIYA_PROP_SHELL_APPLICATION, &app, NULL);
|
||||||
|
assert(app);
|
||||||
|
|
||||||
|
DiyaShellWindow* self = DIYA_SHELL_WINDOW(g_object_new (window_type, "application", app, "shell",shell, NULL));
|
||||||
|
DiyaShellWindowClass *class = DIYA_SHELL_WINDOW_GET_CLASS(self);
|
||||||
|
if(class->setup)
|
||||||
|
{
|
||||||
|
class->setup(self);
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpointer diya_shell_window_get_shell(DiyaShellWindow* self)
|
||||||
|
{
|
||||||
|
DiyaShellWindowPrivate* priv = diya_shell_window_get_instance_private(self);
|
||||||
|
return priv->shell;
|
||||||
|
}
|
18
src/widgets/base-widgets.h
Normal file
18
src/widgets/base-widgets.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef DIYA_BASE_WIDGETS_H
|
||||||
|
#define DIYA_BASE_WIDGETS_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#define DIYA_TYPE_SHELL_WINDOW (diya_shell_window_get_type())
|
||||||
|
G_DECLARE_DERIVABLE_TYPE(DiyaShellWindow, diya_shell_window, DIYA, SHELL_WINDOW, GtkApplicationWindow)
|
||||||
|
struct _DiyaShellWindowClass
|
||||||
|
{
|
||||||
|
GtkApplicationWindowClass parent_class;
|
||||||
|
void (*setup)(DiyaShellWindow* self);
|
||||||
|
};
|
||||||
|
gpointer diya_shell_window_get_shell(DiyaShellWindow* self);
|
||||||
|
DiyaShellWindow* diya_shell_window_new(GType window_type, gpointer shell);
|
||||||
|
|
||||||
|
#endif
|
353
src/widgets/dashboard-widget.c
Normal file
353
src/widgets/dashboard-widget.c
Normal file
@ -0,0 +1,353 @@
|
|||||||
|
#include "dashboard-widget.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of list model
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct _DiyaDashboardListModel
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
GList *appinfos;
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint diya_dashboard_list_model_get_n_items(GListModel *list)
|
||||||
|
{
|
||||||
|
DiyaDashboardListModel *self = DIYA_DASHBOARD_LIST_MODEL(list);
|
||||||
|
return g_list_length(self->appinfos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gpointer diya_dashboard_list_model_get_item(GListModel *list, guint position)
|
||||||
|
{
|
||||||
|
DiyaDashboardListModel *self = DIYA_DASHBOARD_LIST_MODEL(list);
|
||||||
|
if(self->appinfos == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(position >= g_list_length(self->appinfos))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return g_object_ref(g_list_nth_data(self->appinfos, position));
|
||||||
|
}
|
||||||
|
|
||||||
|
static GType diya_dashboard_list_model_get_item_type(GListModel *list)
|
||||||
|
{
|
||||||
|
(void)list; // Unused parameter
|
||||||
|
return G_TYPE_APP_INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_dashboard_list_model_interface_init(GListModelInterface *iface)
|
||||||
|
{
|
||||||
|
iface->get_n_items = diya_dashboard_list_model_get_n_items;
|
||||||
|
iface->get_item = diya_dashboard_list_model_get_item;
|
||||||
|
iface->get_item_type = diya_dashboard_list_model_get_item_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_CODE(DiyaDashboardListModel, diya_dashboard_list_model, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(G_TYPE_LIST_MODEL, diya_dashboard_list_model_interface_init))
|
||||||
|
|
||||||
|
static void diya_dashboard_list_model_finalize(GObject *object)
|
||||||
|
{
|
||||||
|
g_debug("diya_dashboard_list_model_finalize");
|
||||||
|
DiyaDashboardListModel *self = DIYA_DASHBOARD_LIST_MODEL(object);
|
||||||
|
g_list_free_full(self->appinfos, g_object_unref);
|
||||||
|
G_OBJECT_CLASS(diya_dashboard_list_model_parent_class)->finalize(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_dashboard_list_model_dispose(GObject *object)
|
||||||
|
{
|
||||||
|
(void)object;
|
||||||
|
g_debug("diya_dashboard_list_model_dispose");
|
||||||
|
G_OBJECT_CLASS(diya_dashboard_list_model_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_dashboard_list_model_init(DiyaDashboardListModel *self)
|
||||||
|
{
|
||||||
|
self->appinfos = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_dashboard_list_model_class_init(DiyaDashboardListModelClass *class)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
|
gobject_class->finalize = diya_dashboard_list_model_finalize;
|
||||||
|
gobject_class->dispose = diya_dashboard_list_model_dispose;
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_dashboard_list_model_append(DiyaDashboardListModel *self, GAppInfo *info)
|
||||||
|
{
|
||||||
|
self->appinfos = g_list_append(self->appinfos, g_object_ref(info));
|
||||||
|
// self->appinfos = g_list_reverse(self->appinfos);
|
||||||
|
g_list_model_items_changed(G_LIST_MODEL(self), g_list_length(self->appinfos) - 1, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint diya_dashboard_app_info_cmp(GAppInfo *a, GAppInfo *b)
|
||||||
|
{
|
||||||
|
return !g_app_info_equal(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean diya_dashboard_list_model_contain(DiyaDashboardListModel *self, GAppInfo *info)
|
||||||
|
{
|
||||||
|
GList *found = NULL;
|
||||||
|
found = g_list_find_custom(self->appinfos, info, (GCompareFunc)diya_dashboard_app_info_cmp);
|
||||||
|
return found != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement of Dashboard widget
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct _DiyaDashboardWidget
|
||||||
|
{
|
||||||
|
DiyaShellWindow parent;
|
||||||
|
GtkWidget *revealer;
|
||||||
|
GtkWidget *search_entry;
|
||||||
|
GtkWidget *app_list_box;
|
||||||
|
DiyaDashboardListModel *list_model;
|
||||||
|
GtkSortListModel *sort_model;
|
||||||
|
GtkFilterListModel *proxy_model;
|
||||||
|
GtkSorter *sorter;
|
||||||
|
GtkFilter *filter;
|
||||||
|
bool active;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
NO_PROP,
|
||||||
|
PROP_ACTIVE,
|
||||||
|
N_PROPERTIES
|
||||||
|
};
|
||||||
|
|
||||||
|
static GParamSpec *g_prop[N_PROPERTIES] = {0};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(DiyaDashboardWidget, diya_dashboard_widget, DIYA_TYPE_SHELL_WINDOW)
|
||||||
|
|
||||||
|
static void diya_dashboard_widget_dispose(GObject *object)
|
||||||
|
{
|
||||||
|
DiyaDashboardWidget *self = DIYA_DASHBOARD_WIDGET(object);
|
||||||
|
g_debug("diya_dashboard_widget_dispose");
|
||||||
|
if (self->proxy_model)
|
||||||
|
{
|
||||||
|
g_object_unref(self->proxy_model);
|
||||||
|
}
|
||||||
|
// verify if the list model + sorter is also unref
|
||||||
|
G_OBJECT_CLASS(diya_dashboard_widget_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_dashboard_app_launch(GtkFlowBox *box, GtkFlowBoxChild *child, gpointer user_data)
|
||||||
|
{
|
||||||
|
(void)box; // Unused parameter
|
||||||
|
DiyaDashboardWidget *self = DIYA_DASHBOARD_WIDGET(user_data);
|
||||||
|
int current_index = gtk_flow_box_child_get_index(child);
|
||||||
|
if (current_index < 0)
|
||||||
|
{
|
||||||
|
g_warning("Invalid child index: %d", current_index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GAppInfo *app = G_APP_INFO(g_list_model_get_item(G_LIST_MODEL(self->proxy_model), current_index));
|
||||||
|
assert(app);
|
||||||
|
diya_shell_launch(diya_shell_window_get_shell(DIYA_SHELL_WINDOW(self)), app);
|
||||||
|
g_object_set(self, DIYA_PROP_DASHBOARD_ACTIVE, false, NULL);
|
||||||
|
g_object_unref(app);
|
||||||
|
}
|
||||||
|
static void diya_dashboard_app_icon_clicked(GtkWidget *widget, gpointer user_data)
|
||||||
|
{
|
||||||
|
// relay signal to the GTK_FLOW_BOX_CHILD parent
|
||||||
|
g_signal_emit_by_name(gtk_widget_get_parent(widget), "activate", user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkWidget *diya_dashboard_create_app_icon_widget(void *item, void *user_data)
|
||||||
|
{
|
||||||
|
(void)user_data; // Unused parameter
|
||||||
|
GAppInfo *app_info = G_APP_INFO(item);
|
||||||
|
const gchar *name = g_app_info_get_display_name(app_info);
|
||||||
|
GIcon *icon = g_app_info_get_icon(app_info);
|
||||||
|
GtkWidget *widget = gtk_button_new_with_label(name);
|
||||||
|
if (icon)
|
||||||
|
{
|
||||||
|
g_debug("app_info %s has icon %s", name, g_icon_to_string(icon));
|
||||||
|
// gtk_button_set_icon_name(GTK_BUTTON(widget), g_icon_to_string(icon));
|
||||||
|
}
|
||||||
|
g_signal_connect(widget, "clicked", G_CALLBACK(diya_dashboard_app_icon_clicked), user_data);
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int diya_dashboard_app_info_sort_cmp(GAppInfo *a, GAppInfo *b, gpointer user_data)
|
||||||
|
{
|
||||||
|
(void)user_data; // Unused parameter
|
||||||
|
const gchar *name_a = g_app_info_get_display_name(a);
|
||||||
|
const gchar *name_b = g_app_info_get_display_name(b);
|
||||||
|
return g_strcmp0(name_a, name_b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean diya_app_info_filter_func(GAppInfo *app_info, gpointer user_data)
|
||||||
|
{
|
||||||
|
DiyaDashboardWidget *self = DIYA_DASHBOARD_WIDGET(user_data);
|
||||||
|
gchar *text = g_utf8_strdown(gtk_editable_get_text(GTK_EDITABLE(self->search_entry)), -1);
|
||||||
|
if (strlen(text) == 0)
|
||||||
|
{
|
||||||
|
g_free(text);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
gchar *name = g_utf8_strdown(g_app_info_get_display_name(app_info), -1);
|
||||||
|
if(!name)
|
||||||
|
{
|
||||||
|
g_free(text);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
gboolean result = g_str_has_prefix(name, text);
|
||||||
|
g_free(text);
|
||||||
|
g_free(name);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_dashboard_search_text_changed(GtkEntry *entry, DiyaDashboardWidget *self)
|
||||||
|
{
|
||||||
|
(void)entry; // Unused parameter
|
||||||
|
gtk_filter_changed(self->filter, GTK_FILTER_CHANGE_DIFFERENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_dashboard_widget_init(DiyaDashboardWidget *self)
|
||||||
|
{
|
||||||
|
g_debug("diya_dashboard_widget_init");
|
||||||
|
gtk_widget_init_template(GTK_WIDGET(self));
|
||||||
|
self->active = false;
|
||||||
|
|
||||||
|
// int layer shell for window
|
||||||
|
gtk_layer_init_for_window(GTK_WINDOW(self));
|
||||||
|
// anchor window to all edges
|
||||||
|
gtk_layer_set_anchor(GTK_WINDOW(self), GTK_LAYER_SHELL_EDGE_LEFT, true);
|
||||||
|
gtk_layer_set_anchor(GTK_WINDOW(self), GTK_LAYER_SHELL_EDGE_RIGHT, true);
|
||||||
|
gtk_layer_set_anchor(GTK_WINDOW(self), GTK_LAYER_SHELL_EDGE_TOP, true);
|
||||||
|
gtk_layer_set_anchor(GTK_WINDOW(self), GTK_LAYER_SHELL_EDGE_BOTTOM, true);
|
||||||
|
gtk_layer_set_namespace(GTK_WINDOW(self), "diya-dashboard");
|
||||||
|
// set margin on window
|
||||||
|
for (int i = 0; i < GTK_LAYER_SHELL_EDGE_ENTRY_NUMBER; i++)
|
||||||
|
gtk_layer_set_margin(GTK_WINDOW(self), i, 0);
|
||||||
|
gtk_layer_set_layer(GTK_WINDOW(self), GTK_LAYER_SHELL_LAYER_TOP);
|
||||||
|
// gtk_layer_set_keyboard_mode (GTK_WINDOW(self), GTK_LAYER_SHELL_KEYBOARD_MODE_ON_DEMAND);
|
||||||
|
// the top launcher shall be exclusive
|
||||||
|
// gtk_layer_auto_exclusive_zone_enable (GTK_WINDOW(self));
|
||||||
|
gtk_layer_set_keyboard_mode(GTK_WINDOW(self), GTK_LAYER_SHELL_KEYBOARD_MODE_ON_DEMAND);
|
||||||
|
// gtk_widget_set_can_focus(GTK_WIDGET(self), true);
|
||||||
|
// gtk_widget_set_name(GTK_WIDGET(dashboard),NAMESPACE);
|
||||||
|
// gtk_window_set_default_size(GTK_WINDOW(dashboard), 48, 48);
|
||||||
|
|
||||||
|
// event controller
|
||||||
|
// GtkEventController *event_controller = gtk_event_controller_key_new();
|
||||||
|
// g_signal_connect(event_controller, "key-pressed", G_CALLBACK(on_diya_dashboard_key_press), self);
|
||||||
|
// gtk_widget_add_controller(GTK_WIDGET(self), event_controller);
|
||||||
|
self->list_model = g_object_new(DIYA_TYPE_DASHBOARD_LIST_MODEL, NULL);
|
||||||
|
self->sorter = GTK_SORTER(gtk_custom_sorter_new((GCompareDataFunc)diya_dashboard_app_info_sort_cmp, NULL, NULL));
|
||||||
|
self->sort_model = gtk_sort_list_model_new(G_LIST_MODEL(self->list_model), self->sorter);
|
||||||
|
self->filter = GTK_FILTER(gtk_custom_filter_new((GtkCustomFilterFunc)diya_app_info_filter_func, self, NULL));
|
||||||
|
self->proxy_model = gtk_filter_list_model_new(G_LIST_MODEL(self->sort_model), self->filter);
|
||||||
|
gtk_flow_box_bind_model(GTK_FLOW_BOX(self->app_list_box), G_LIST_MODEL(self->proxy_model), diya_dashboard_create_app_icon_widget, self, NULL);
|
||||||
|
|
||||||
|
gtk_flow_box_set_selection_mode(GTK_FLOW_BOX(self->app_list_box), GTK_SELECTION_SINGLE);
|
||||||
|
gtk_flow_box_set_activate_on_single_click(GTK_FLOW_BOX(self->app_list_box), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_dashboard_show(DiyaDashboardWidget *self)
|
||||||
|
{
|
||||||
|
gtk_window_present(GTK_WINDOW(self));
|
||||||
|
// gtk_widget_set_visible(GTK_WIDGET(self), true);
|
||||||
|
gtk_revealer_set_reveal_child(GTK_REVEALER(self->revealer), true);
|
||||||
|
gtk_window_set_focus(GTK_WINDOW(self), self->search_entry);
|
||||||
|
// gtk_widget_grab_focus( GTK_WIDGET(self->search_entry));
|
||||||
|
GList *apps = g_app_info_get_all();
|
||||||
|
GList *l;
|
||||||
|
for (l = apps; l != NULL; l = l->next)
|
||||||
|
{
|
||||||
|
GAppInfo *info = l->data;
|
||||||
|
if (diya_dashboard_list_model_contain(self->list_model, info))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
g_debug("add AppInfo %s", g_app_info_get_id(info));
|
||||||
|
diya_dashboard_list_model_append(self->list_model, info);
|
||||||
|
}
|
||||||
|
g_list_free_full(apps, g_object_unref);
|
||||||
|
gtk_sorter_changed(self->sorter, GTK_SORTER_CHANGE_INVERTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_dashboard_hide(DiyaDashboardWidget *self)
|
||||||
|
{
|
||||||
|
gtk_revealer_set_reveal_child(GTK_REVEALER(self->revealer), false);
|
||||||
|
gtk_widget_set_visible(GTK_WIDGET(self), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_dashboard_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
DiyaDashboardWidget *self = DIYA_DASHBOARD_WIDGET(object);
|
||||||
|
|
||||||
|
switch (property_id)
|
||||||
|
{
|
||||||
|
case PROP_ACTIVE:
|
||||||
|
{
|
||||||
|
gboolean active = g_value_get_boolean(value);
|
||||||
|
if (self->active == active)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self->active = active;
|
||||||
|
if (self->active)
|
||||||
|
{
|
||||||
|
diya_dashboard_show(self);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diya_dashboard_hide(self);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_dashboard_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
DiyaDashboardWidget *self = DIYA_DASHBOARD_WIDGET(object);
|
||||||
|
switch (property_id)
|
||||||
|
{
|
||||||
|
case PROP_ACTIVE:
|
||||||
|
g_value_set_boolean(value, self->active);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_dashboard_widget_class_init(DiyaDashboardWidgetClass *class)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
|
gobject_class->dispose = diya_dashboard_widget_dispose;
|
||||||
|
gobject_class->set_property = diya_dashboard_set_property;
|
||||||
|
gobject_class->get_property = diya_dashboard_get_property;
|
||||||
|
|
||||||
|
// DiyaShellWindowClass* base_class = DIYA_SHELL_WINDOW_CLASS(class);
|
||||||
|
// base_class->setup = diya_dashboard_widget_setup;
|
||||||
|
|
||||||
|
gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS(class), "/dev/iohub/diya/shell/ui/dashboard.ui");
|
||||||
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), DiyaDashboardWidget, revealer);
|
||||||
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), DiyaDashboardWidget, search_entry);
|
||||||
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), DiyaDashboardWidget, app_list_box);
|
||||||
|
|
||||||
|
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), diya_dashboard_app_launch);
|
||||||
|
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), diya_dashboard_search_text_changed);
|
||||||
|
|
||||||
|
gtk_widget_class_set_css_name(GTK_WIDGET_CLASS(class), "diya-dashboard");
|
||||||
|
// gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS (class), ExampleAppWindow, stack);
|
||||||
|
// gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), search_text_changed);
|
||||||
|
|
||||||
|
g_prop[PROP_ACTIVE] = g_param_spec_boolean(DIYA_PROP_DASHBOARD_ACTIVE, NULL, "Active the dashboard", false, G_PARAM_READWRITE); //
|
||||||
|
|
||||||
|
g_object_class_install_properties(gobject_class, N_PROPERTIES, g_prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean diya_dashboard_is_active(DiyaDashboardWidget *self)
|
||||||
|
{
|
||||||
|
return self->active;
|
||||||
|
}
|
17
src/widgets/dashboard-widget.h
Normal file
17
src/widgets/dashboard-widget.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef DIYA_DASHBOARD_WIDGET_H
|
||||||
|
#define DIYA_DASHBOARD_WIDGET_H
|
||||||
|
|
||||||
|
#include "session-shell.h"
|
||||||
|
#include "base-widgets.h"
|
||||||
|
|
||||||
|
#define DIYA_PROP_DASHBOARD_ACTIVE "active"
|
||||||
|
|
||||||
|
#define DIYA_TYPE_DASHBOARD_WIDGET (diya_dashboard_widget_get_type())
|
||||||
|
G_DECLARE_FINAL_TYPE (DiyaDashboardWidget, diya_dashboard_widget, DIYA, DASHBOARD_WIDGET, DiyaShellWindow)
|
||||||
|
|
||||||
|
#define DIYA_TYPE_DASHBOARD_LIST_MODEL (diya_dashboard_list_model_get_type())
|
||||||
|
G_DECLARE_FINAL_TYPE (DiyaDashboardListModel, diya_dashboard_list_model, DIYA, DASHBOARD_LIST_MODEL, GObject)
|
||||||
|
|
||||||
|
gboolean diya_dashboard_is_active(DiyaDashboardWidget* self);
|
||||||
|
|
||||||
|
#endif
|
413
src/widgets/taskbar-widget.c
Normal file
413
src/widgets/taskbar-widget.c
Normal file
@ -0,0 +1,413 @@
|
|||||||
|
#include "taskbar-widget.h"
|
||||||
|
#include "foreign.h"
|
||||||
|
|
||||||
|
#define DEFAULT_APP_ICON_NAME "application-x-executable-symbolic"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of list model
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct _DiyaTaskbarListModel
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
GList *apps;
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint diya_taskbar_list_model_get_n_items(GListModel *list)
|
||||||
|
{
|
||||||
|
DiyaTaskbarListModel *self = DIYA_TASKBAR_LIST_MODEL(list);
|
||||||
|
return g_list_length(self->apps);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gpointer diya_taskbar_list_model_get_item(GListModel *list, guint position)
|
||||||
|
{
|
||||||
|
DiyaTaskbarListModel *self = DIYA_TASKBAR_LIST_MODEL(list);
|
||||||
|
if(self->apps == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(position >= g_list_length(self->apps))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return g_object_ref(g_list_nth_data(self->apps, position));
|
||||||
|
}
|
||||||
|
|
||||||
|
static GType diya_taskbar_list_model_get_item_type(GListModel *list)
|
||||||
|
{
|
||||||
|
(void)list; // Unused parameter
|
||||||
|
return DIYA_TYPE_FOREIGN_WINDOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_taskbar_list_model_interface_init(GListModelInterface *iface)
|
||||||
|
{
|
||||||
|
iface->get_n_items = diya_taskbar_list_model_get_n_items;
|
||||||
|
iface->get_item = diya_taskbar_list_model_get_item;
|
||||||
|
iface->get_item_type = diya_taskbar_list_model_get_item_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_CODE(DiyaTaskbarListModel, diya_taskbar_list_model, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(G_TYPE_LIST_MODEL, diya_taskbar_list_model_interface_init))
|
||||||
|
|
||||||
|
static void diya_taskbar_list_model_finalize(GObject *object)
|
||||||
|
{
|
||||||
|
g_debug("diya_taskbar_list_model_finalize");
|
||||||
|
DiyaTaskbarListModel *self = DIYA_TASKBAR_LIST_MODEL(object);
|
||||||
|
g_list_free_full(self->apps, g_object_unref);
|
||||||
|
G_OBJECT_CLASS(diya_taskbar_list_model_parent_class)->finalize(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_taskbar_list_model_dispose(GObject *object)
|
||||||
|
{
|
||||||
|
(void)object;
|
||||||
|
g_debug("diya_taskbar_list_model_dispose");
|
||||||
|
G_OBJECT_CLASS(diya_taskbar_list_model_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_taskbar_list_model_init(DiyaTaskbarListModel *self)
|
||||||
|
{
|
||||||
|
self->apps = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_taskbar_list_model_class_init(DiyaTaskbarListModelClass *class)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
|
gobject_class->finalize = diya_taskbar_list_model_finalize;
|
||||||
|
gobject_class->dispose = diya_taskbar_list_model_dispose;
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_taskbar_list_model_append(DiyaTaskbarListModel *self, DiyaForeignWindow *window)
|
||||||
|
{
|
||||||
|
self->apps = g_list_append(self->apps, g_object_ref(window));
|
||||||
|
// self->appinfos = g_list_reverse(self->appinfos);
|
||||||
|
g_list_model_items_changed(G_LIST_MODEL(self), g_list_length(self->apps) - 1, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_taskbar_list_model_remove(DiyaTaskbarListModel *self, DiyaForeignWindow *window)
|
||||||
|
{
|
||||||
|
gint index = g_list_index(self->apps, window);
|
||||||
|
if (index < 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self->apps = g_list_remove(self->apps, window);
|
||||||
|
g_object_unref(window);
|
||||||
|
g_list_model_items_changed(G_LIST_MODEL(self), index, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean diya_taskbar_list_model_contain(DiyaTaskbarListModel *self, DiyaForeignWindow *info)
|
||||||
|
{
|
||||||
|
GList *found = NULL;
|
||||||
|
found = g_list_find(self->apps, info);
|
||||||
|
return found != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement of taskbar widget
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct _DiyaTaskbarWidget
|
||||||
|
{
|
||||||
|
DiyaShellWindow parent;
|
||||||
|
GtkWidget *btn_toggle;
|
||||||
|
bool active_dashboard;
|
||||||
|
GtkWidget *apps_list;
|
||||||
|
GtkSingleSelection *proxy_model;
|
||||||
|
DiyaTaskbarListModel *model;
|
||||||
|
GtkListItemFactory *factory;
|
||||||
|
guint selection_changed_sig_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
NO_PROP,
|
||||||
|
PROP_SHOW_DASHBOARD,
|
||||||
|
N_PROPERTIES
|
||||||
|
};
|
||||||
|
|
||||||
|
static GParamSpec *g_prop[N_PROPERTIES] = {0};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(DiyaTaskbarWidget, diya_taskbar_widget, DIYA_TYPE_SHELL_WINDOW)
|
||||||
|
|
||||||
|
static void diya_taskbar_widget_dispose(GObject *object)
|
||||||
|
{
|
||||||
|
DiyaTaskbarWidget *self = DIYA_TASKBAR_WIDGET(object);
|
||||||
|
g_debug("diya_taskbar_widget_dispose");
|
||||||
|
if (self->proxy_model)
|
||||||
|
{
|
||||||
|
g_object_unref(self->proxy_model);
|
||||||
|
}
|
||||||
|
if (self->factory)
|
||||||
|
{
|
||||||
|
g_object_unref(self->factory);
|
||||||
|
}
|
||||||
|
G_OBJECT_CLASS(diya_taskbar_widget_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_taskbar_setup_apps_list_cb(GtkListItemFactory *factory, GtkListItem *list_item)
|
||||||
|
{
|
||||||
|
(void) factory;
|
||||||
|
GtkWidget *image;
|
||||||
|
image = gtk_image_new();
|
||||||
|
gtk_image_set_icon_size(GTK_IMAGE(image), GTK_ICON_SIZE_LARGE);
|
||||||
|
gtk_list_item_set_child(list_item, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_taskbar_bind_apps_list_cb(GtkListItemFactory *factory, GtkListItem *list_item)
|
||||||
|
{
|
||||||
|
(void) factory;
|
||||||
|
GtkWidget *image;
|
||||||
|
DiyaForeignWindow *win;
|
||||||
|
image = gtk_list_item_get_child(list_item);
|
||||||
|
win = gtk_list_item_get_item(list_item);
|
||||||
|
GAppInfo* info = diya_foreign_window_get_app_info(win);
|
||||||
|
if(info)
|
||||||
|
{
|
||||||
|
assert(G_IS_APP_INFO(info));
|
||||||
|
gtk_image_set_from_gicon(GTK_IMAGE(image), g_app_info_get_icon(info));
|
||||||
|
g_object_unref(info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// get default icon from theme
|
||||||
|
GtkIconTheme* theme = gtk_icon_theme_get_for_display(gdk_display_get_default());
|
||||||
|
if(gtk_icon_theme_has_icon(theme, DEFAULT_APP_ICON_NAME))
|
||||||
|
{
|
||||||
|
gtk_image_set_from_icon_name(GTK_IMAGE(image), DEFAULT_APP_ICON_NAME);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// fallback to default icon in resource
|
||||||
|
gtk_image_set_from_resource(GTK_IMAGE(image), "/dev/iohub/diya/shell/icons/scalable/gear");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static guint g_list_model_get_item_index(GListModel *model, gpointer item)
|
||||||
|
{
|
||||||
|
for(guint i = 0; i < g_list_model_get_n_items(model); i++)
|
||||||
|
{
|
||||||
|
if(g_list_model_get_item(model, i) == item)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return GTK_INVALID_LIST_POSITION;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_foreign_window_state_changed(DiyaSessionShell* shell, DiyaForeignWindow* win, enum diya_win_state state, DiyaTaskbarWidget *self)
|
||||||
|
{
|
||||||
|
(void) shell;
|
||||||
|
DiyaForeignWindow *top_level = diya_foreign_window_get_top_level(win);
|
||||||
|
guint index = g_list_model_get_item_index(G_LIST_MODEL(self->model), top_level);
|
||||||
|
guint current_index = gtk_single_selection_get_selected(self->proxy_model);
|
||||||
|
g_debug("Current index %d, selected index %d", current_index, index);
|
||||||
|
|
||||||
|
g_signal_handler_block(self->proxy_model, self->selection_changed_sig_id);
|
||||||
|
if((state & DIYA_WIN_STATE_FOCUS) && !(state & DIYA_WIN_STATE_MINIMIZE))
|
||||||
|
{
|
||||||
|
if(index != GTK_INVALID_LIST_POSITION)
|
||||||
|
{
|
||||||
|
gtk_selection_model_select_item(GTK_SELECTION_MODEL(self->proxy_model), index, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// get the widget under the cursor
|
||||||
|
|
||||||
|
if(current_index == index)
|
||||||
|
{
|
||||||
|
gtk_selection_model_unselect_item(GTK_SELECTION_MODEL(self->proxy_model), current_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_signal_handler_unblock(self->proxy_model, self->selection_changed_sig_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_foreign_window_added(DiyaSessionShell *shell, DiyaForeignWindow *win, DiyaTaskbarWidget *self)
|
||||||
|
{
|
||||||
|
(void) shell;
|
||||||
|
g_debug("Window added %s (toplevel %d)", diya_object_to_string(win), diya_foreign_window_is_toplevel(win));
|
||||||
|
if(!diya_foreign_window_is_toplevel(win))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(diya_taskbar_list_model_contain(self->model, win))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
diya_taskbar_list_model_append(self->model, win);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_foreign_window_removed(DiyaSessionShell *shell, DiyaForeignWindow *win, DiyaTaskbarWidget *self)
|
||||||
|
{
|
||||||
|
(void) shell;
|
||||||
|
if (!diya_foreign_window_is_toplevel(win))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (diya_taskbar_list_model_contain(self->model, win))
|
||||||
|
{
|
||||||
|
diya_taskbar_list_model_remove(self->model, win);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_taskbar_list_model_selection_changed_cb(GtkSelectionModel *model, guint position, guint n_items, gpointer user_data)
|
||||||
|
{
|
||||||
|
(void) n_items;
|
||||||
|
(void) user_data;
|
||||||
|
(void) position;
|
||||||
|
DiyaForeignWindow *win = gtk_single_selection_get_selected_item(GTK_SINGLE_SELECTION(model));
|
||||||
|
DiyaTaskbarWidget *self = DIYA_TASKBAR_WIDGET(user_data);
|
||||||
|
if(gtk_selection_model_is_selected(GTK_SELECTION_MODEL(model), position))
|
||||||
|
{
|
||||||
|
g_debug("Activating window: %s", diya_object_to_string(win));
|
||||||
|
enum diya_win_state state = diya_foreign_window_get_state(win);
|
||||||
|
if(state & DIYA_WIN_STATE_MINIMIZE)
|
||||||
|
{
|
||||||
|
diya_foreign_window_set_state(win, DIYA_WIN_STATE_MINIMIZE, false);
|
||||||
|
}
|
||||||
|
if(self->active_dashboard)
|
||||||
|
{
|
||||||
|
g_object_set(self, DIYA_PROP_TASKBAR_SHOW_DASHBOARD, !self->active_dashboard, NULL);
|
||||||
|
}
|
||||||
|
diya_foreign_window_set_state(win, DIYA_WIN_STATE_FOCUS, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diya_foreign_window_set_state(win, DIYA_WIN_STATE_MINIMIZE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_taskbar_applist_enter(GtkEventControllerFocus *controller, DiyaTaskbarWidget* self)
|
||||||
|
{
|
||||||
|
g_debug("diya_taskbar_applist_enter");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void diya_taskbar_applist_leave(GtkEventControllerFocus *controller, DiyaTaskbarWidget* self)
|
||||||
|
{
|
||||||
|
g_debug("diya_taskbar_applist_leaver");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_taskbar_widget_init(DiyaTaskbarWidget *self)
|
||||||
|
{
|
||||||
|
g_debug("diya_taskbar_widget_init");
|
||||||
|
gtk_widget_init_template(GTK_WIDGET(self));
|
||||||
|
self->active_dashboard = false;
|
||||||
|
|
||||||
|
// int layer shell for window
|
||||||
|
gtk_layer_init_for_window(GTK_WINDOW(self));
|
||||||
|
// anchor window to all edges
|
||||||
|
gtk_layer_set_anchor(GTK_WINDOW(self), GTK_LAYER_SHELL_EDGE_LEFT, true);
|
||||||
|
gtk_layer_set_anchor(GTK_WINDOW(self), GTK_LAYER_SHELL_EDGE_RIGHT, true);
|
||||||
|
gtk_layer_set_anchor(GTK_WINDOW(self), GTK_LAYER_SHELL_EDGE_TOP, false);
|
||||||
|
gtk_layer_set_anchor(GTK_WINDOW(self), GTK_LAYER_SHELL_EDGE_BOTTOM, true);
|
||||||
|
gtk_layer_set_namespace(GTK_WINDOW(self), "diya-taskbar");
|
||||||
|
// set margin on window
|
||||||
|
for (int i = 0; i < GTK_LAYER_SHELL_EDGE_ENTRY_NUMBER; i++)
|
||||||
|
gtk_layer_set_margin(GTK_WINDOW(self), i, 0);
|
||||||
|
gtk_layer_set_layer(GTK_WINDOW(self), GTK_LAYER_SHELL_LAYER_TOP);
|
||||||
|
gtk_layer_set_keyboard_mode(GTK_WINDOW(self), GTK_LAYER_SHELL_KEYBOARD_MODE_ON_DEMAND);
|
||||||
|
// the top launcher shall be exclusive
|
||||||
|
gtk_layer_auto_exclusive_zone_enable(GTK_WINDOW(self));
|
||||||
|
|
||||||
|
g_object_bind_property(self->btn_toggle, "active", self, DIYA_PROP_TASKBAR_SHOW_DASHBOARD, G_BINDING_BIDIRECTIONAL);
|
||||||
|
|
||||||
|
self->factory = gtk_signal_list_item_factory_new();
|
||||||
|
g_signal_connect(self->factory, "setup", G_CALLBACK(diya_taskbar_setup_apps_list_cb), NULL);
|
||||||
|
g_signal_connect(self->factory, "bind", G_CALLBACK(diya_taskbar_bind_apps_list_cb), NULL);
|
||||||
|
// applists
|
||||||
|
self->model = DIYA_TASKBAR_LIST_MODEL(g_object_new(DIYA_TYPE_TASKBAR_LIST_MODEL, NULL));
|
||||||
|
self->proxy_model = gtk_single_selection_new (G_LIST_MODEL(self->model));
|
||||||
|
gtk_single_selection_set_autoselect(self->proxy_model, false);
|
||||||
|
gtk_single_selection_set_can_unselect(self->proxy_model, true);
|
||||||
|
gtk_list_view_set_model(GTK_LIST_VIEW(self->apps_list), GTK_SELECTION_MODEL(self->proxy_model));
|
||||||
|
gtk_list_view_set_factory(GTK_LIST_VIEW(self->apps_list), GTK_LIST_ITEM_FACTORY(self->factory));
|
||||||
|
// gtk_list_view_set_single_click_activate(GTK_LIST_VIEW(self->apps_list), true);
|
||||||
|
|
||||||
|
self->selection_changed_sig_id = g_signal_connect(GTK_SELECTION_MODEL(self->proxy_model), "selection-changed", G_CALLBACK(diya_taskbar_list_model_selection_changed_cb), self);
|
||||||
|
|
||||||
|
// event handle
|
||||||
|
GtkEventController *controller = gtk_event_controller_focus_new();
|
||||||
|
g_signal_connect(controller, "enter", G_CALLBACK(diya_taskbar_applist_enter), self);
|
||||||
|
g_signal_connect(controller, "leave", G_CALLBACK(diya_taskbar_applist_leave), self);
|
||||||
|
gtk_widget_add_controller(GTK_WIDGET(self->apps_list), GTK_EVENT_CONTROLLER(controller));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_taskbar_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
DiyaTaskbarWidget *self = DIYA_TASKBAR_WIDGET(object);
|
||||||
|
|
||||||
|
switch (property_id)
|
||||||
|
{
|
||||||
|
case PROP_SHOW_DASHBOARD:
|
||||||
|
self->active_dashboard = g_value_get_boolean(value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_taskbar_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
DiyaTaskbarWidget *self = DIYA_TASKBAR_WIDGET(object);
|
||||||
|
switch (property_id)
|
||||||
|
{
|
||||||
|
case PROP_SHOW_DASHBOARD:
|
||||||
|
g_value_set_boolean(value, self->active_dashboard);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
static void diya_dashboard_toggle(GtkToggleButton* btn, DiyaTaskbarWidget* self)
|
||||||
|
{
|
||||||
|
g_warning("TODDLDLDL");
|
||||||
|
if(gtk_toggle_button_get_active(btn))
|
||||||
|
{
|
||||||
|
gtk_layer_set_exclusive_zone(GTK_WINDOW(self), 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gtk_layer_auto_exclusive_zone_enable (GTK_WINDOW(self));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void diya_taskbar_widget_setup(DiyaShellWindow* win)
|
||||||
|
{
|
||||||
|
DiyaTaskbarWidget* self = DIYA_TASKBAR_WIDGET(win);
|
||||||
|
DiyaSessionShell *shell = DIYA_SESSION_SHELL(diya_shell_window_get_shell(DIYA_SHELL_WINDOW(self)));
|
||||||
|
g_signal_connect(shell, DIYA_SIGNAL_FOREIGN_WINDOW_ADDED, G_CALLBACK(on_foreign_window_added), self);
|
||||||
|
g_signal_connect(shell, DIYA_SIGNAL_FOREIGN_WINDOW_STATE_CHANGED, G_CALLBACK(on_foreign_window_state_changed), self);
|
||||||
|
g_signal_connect(shell, DIYA_SIGNAL_FOREIGN_WINDOW_REMOVED, G_CALLBACK(on_foreign_window_removed), self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_taskbar_widget_class_init(DiyaTaskbarWidgetClass *class)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
|
gobject_class->dispose = diya_taskbar_widget_dispose;
|
||||||
|
gobject_class->set_property = diya_taskbar_set_property;
|
||||||
|
gobject_class->get_property = diya_taskbar_get_property;
|
||||||
|
|
||||||
|
DiyaShellWindowClass *window_class = DIYA_SHELL_WINDOW_CLASS(class);
|
||||||
|
window_class->setup = diya_taskbar_widget_setup;
|
||||||
|
|
||||||
|
gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS(class), "/dev/iohub/diya/shell/ui/taskbar.ui");
|
||||||
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), DiyaTaskbarWidget, btn_toggle);
|
||||||
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), DiyaTaskbarWidget, apps_list);
|
||||||
|
|
||||||
|
// gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), diya_dashboard_toggle);
|
||||||
|
|
||||||
|
gtk_widget_class_set_css_name(GTK_WIDGET_CLASS(class), "diya-taskbar");
|
||||||
|
// gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS (class), ExampleAppWindow, stack);
|
||||||
|
// gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), search_text_changed);
|
||||||
|
|
||||||
|
g_prop[PROP_SHOW_DASHBOARD] = g_param_spec_boolean(DIYA_PROP_TASKBAR_SHOW_DASHBOARD, NULL, "Show/hide dashboard", false, G_PARAM_READWRITE); //
|
||||||
|
|
||||||
|
g_object_class_install_properties(gobject_class, N_PROPERTIES, g_prop);
|
||||||
|
}
|
15
src/widgets/taskbar-widget.h
Normal file
15
src/widgets/taskbar-widget.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef DIYA_TASKBAR_WIDGET_H
|
||||||
|
#define DIYA_TASKBAR_WIDGET_H
|
||||||
|
|
||||||
|
#include "session-shell.h"
|
||||||
|
#include "base-widgets.h"
|
||||||
|
|
||||||
|
#define DIYA_PROP_TASKBAR_SHOW_DASHBOARD "show-taskbar"
|
||||||
|
|
||||||
|
#define DIYA_TYPE_TASKBAR_WIDGET (diya_taskbar_widget_get_type())
|
||||||
|
G_DECLARE_FINAL_TYPE (DiyaTaskbarWidget, diya_taskbar_widget, DIYA, TASKBAR_WIDGET, DiyaShellWindow)
|
||||||
|
|
||||||
|
#define DIYA_TYPE_TASKBAR_LIST_MODEL (diya_taskbar_list_model_get_type())
|
||||||
|
G_DECLARE_FINAL_TYPE (DiyaTaskbarListModel, diya_taskbar_list_model, DIYA, TASKBAR_LIST_MODEL, GObject)
|
||||||
|
|
||||||
|
#endif
|
372
src/widgets/virtual-keyboard-widgets.c
Normal file
372
src/widgets/virtual-keyboard-widgets.c
Normal file
@ -0,0 +1,372 @@
|
|||||||
|
#include "virtual-keyboard-widgets.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief DiyaVkbButton: virtual keyboard button
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct _DiyaVkbButton
|
||||||
|
{
|
||||||
|
GtkWidget super;
|
||||||
|
GtkWidget *labels[3];
|
||||||
|
DiyaVkbKey *key; /*owned by the virtual keyboard*/
|
||||||
|
gulong mod_sig_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_FINAL_TYPE(DiyaVkbButton, diya_vkb_button, GTK_TYPE_WIDGET);
|
||||||
|
|
||||||
|
static void diya_vkb_button_dispose(GObject *object)
|
||||||
|
{
|
||||||
|
DiyaVkbButton *self = DIYA_VKB_BUTTON(object);
|
||||||
|
g_debug("diya_vkb_button_dispose");
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
g_clear_pointer(&self->labels[i], gtk_widget_unparent);
|
||||||
|
}
|
||||||
|
// g_clear_pointer (&demo->label, gtk_widget_unparent);
|
||||||
|
G_OBJECT_CLASS(diya_vkb_button_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_vkb_button_event(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
|
||||||
|
{
|
||||||
|
(void) n_press;
|
||||||
|
(void) x;
|
||||||
|
(void) y;
|
||||||
|
const gchar* evt_name = (gchar*) data;
|
||||||
|
GtkEventController *controller = GTK_EVENT_CONTROLLER(gesture);
|
||||||
|
DiyaVkbButton *self = DIYA_VKB_BUTTON(gtk_event_controller_get_widget(controller));
|
||||||
|
g_signal_emit_by_name(self, evt_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_vkb_button_init(DiyaVkbButton *self)
|
||||||
|
{
|
||||||
|
gchar class_name[32]; /*diya-vkb-btn-level-%d */
|
||||||
|
GtkLayoutManager *grid_layout;
|
||||||
|
self->key = NULL;
|
||||||
|
grid_layout = gtk_widget_get_layout_manager(GTK_WIDGET(self));
|
||||||
|
// gtk_orientable_set_orientation(GTK_ORIENTABLE(box_layout), GTK_ORIENTATION_VERTICAL);
|
||||||
|
// gtk_box_layout_set_spacing (GTK_BOX_LAYOUT (box_layout), 3);
|
||||||
|
gtk_widget_set_can_focus(GTK_WIDGET(self), false);
|
||||||
|
// init labels
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
self->labels[i] = gtk_label_new(NULL);
|
||||||
|
g_snprintf(class_name, sizeof(class_name), "shift-level-%d", i + 1);
|
||||||
|
gtk_widget_add_css_class(self->labels[i], class_name);
|
||||||
|
gtk_widget_set_hexpand(self->labels[i], true);
|
||||||
|
|
||||||
|
gtk_widget_set_parent(self->labels[i], GTK_WIDGET(self));
|
||||||
|
|
||||||
|
GtkGridLayoutChild *grid_child = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(grid_layout, self->labels[i]));
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
/* code */
|
||||||
|
gtk_grid_layout_child_set_row(grid_child, 0);
|
||||||
|
gtk_grid_layout_child_set_column(grid_child, 0);
|
||||||
|
gtk_grid_layout_child_set_column_span(grid_child, 2);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
gtk_grid_layout_child_set_row(grid_child, 1);
|
||||||
|
gtk_grid_layout_child_set_column(grid_child, 0);
|
||||||
|
gtk_widget_set_halign(self->labels[i], GTK_ALIGN_START);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
gtk_grid_layout_child_set_row(grid_child, 1);
|
||||||
|
gtk_grid_layout_child_set_column(grid_child, 1);
|
||||||
|
gtk_widget_set_halign(self->labels[i], GTK_ALIGN_END);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// event handle
|
||||||
|
GtkGesture *controller = gtk_gesture_click_new();
|
||||||
|
g_signal_connect(controller, "pressed", G_CALLBACK(diya_vkb_button_event), DIYA_SIGNAL_VKB_KEY_PRESSED);
|
||||||
|
g_signal_connect(controller, "released", G_CALLBACK(diya_vkb_button_event), DIYA_SIGNAL_VKB_KEY_RELEASED);
|
||||||
|
gtk_widget_add_controller(GTK_WIDGET(self), GTK_EVENT_CONTROLLER(controller));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_vkb_button_class_init(DiyaVkbButtonClass *class)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
|
gobject_class->dispose = diya_vkb_button_dispose;
|
||||||
|
gtk_widget_class_set_css_name(GTK_WIDGET_CLASS(class), "diya-vkb-button");
|
||||||
|
gtk_widget_class_set_layout_manager_type(GTK_WIDGET_CLASS(class), GTK_TYPE_GRID_LAYOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_vkb_button_set_key(DiyaVkbButton* btn, DiyaVkbKey *key)
|
||||||
|
{
|
||||||
|
btn->key = key;
|
||||||
|
for (uint32_t i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
if(key)
|
||||||
|
{
|
||||||
|
const char *cap = diya_vkb_key_get_keycap(key, i);
|
||||||
|
if (cap)
|
||||||
|
{
|
||||||
|
if (i == 1 && diya_vkb_key_is_alphabet(key))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
gtk_label_set_text(GTK_LABEL(btn->labels[i]), cap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gtk_label_set_text(GTK_LABEL(btn->labels[i]), NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DiyaVkbButton *diya_vkb_button_new(DiyaVkbKey *key)
|
||||||
|
{
|
||||||
|
DiyaVkbButton *btn = DIYA_VKB_BUTTON(g_object_new(DIYA_TYPE_VKB_BUTTON, NULL));
|
||||||
|
if(key)
|
||||||
|
{
|
||||||
|
diya_vkb_button_set_key(btn, key);
|
||||||
|
}
|
||||||
|
btn->mod_sig_id = 0;
|
||||||
|
return btn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief DiyaVirtualKeyboardWidget: Virtual keyboard GTK widget
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define VKB_N_CELLS 145
|
||||||
|
#define VKB_ROW_NUM(i) (i / 29)
|
||||||
|
#define VKB_COL_NUM(i) (i % 29)
|
||||||
|
|
||||||
|
static uint32_t g_vkb_layout[] = {
|
||||||
|
49, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
|
||||||
|
23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 51,
|
||||||
|
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 36,
|
||||||
|
50, 94, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 111, 66,
|
||||||
|
9, 206, 64, 65, 0, 108, 113, 116, 114};
|
||||||
|
|
||||||
|
struct _DiyaVirtualKeyboardWidget
|
||||||
|
{
|
||||||
|
GtkWidget super;
|
||||||
|
/**
|
||||||
|
* row 0: 00 - 13
|
||||||
|
* row 1: 14 - 27
|
||||||
|
* row 2: 28 - 40
|
||||||
|
* row 3: 41 - 53
|
||||||
|
* row 4: 54 - 62
|
||||||
|
*/
|
||||||
|
GList *buttons;
|
||||||
|
DiyaVirtualKeyboard *vkb; /*owned by the widget itself*/
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_FINAL_TYPE(DiyaVirtualKeyboardWidget, diya_virtual_keyboard_widget, GTK_TYPE_WIDGET);
|
||||||
|
|
||||||
|
static void diya_virtual_keyboard_widget_dispose(GObject *object)
|
||||||
|
{
|
||||||
|
DiyaVirtualKeyboardWidget *self = DIYA_VIRTUAL_KEYBOARD_WIDGET(object);
|
||||||
|
g_debug("diya_virtual_keyboard_widget_dispose");
|
||||||
|
if (self->buttons)
|
||||||
|
{
|
||||||
|
GList *it = NULL;
|
||||||
|
for (it = self->buttons; it; it = it->next)
|
||||||
|
{
|
||||||
|
if (it->data)
|
||||||
|
{
|
||||||
|
g_clear_pointer(&it->data, gtk_widget_unparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* if(self->vkb)
|
||||||
|
{
|
||||||
|
g_object_unref(self->vkb);
|
||||||
|
} */
|
||||||
|
// g_clear_pointer (&demo->label, gtk_widget_unparent);
|
||||||
|
G_OBJECT_CLASS(diya_virtual_keyboard_widget_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_virtual_keyboard_widget_init(DiyaVirtualKeyboardWidget *self)
|
||||||
|
{
|
||||||
|
// gtk_widget_set_size_request(GTK_WIDGET(self), 600, 400);
|
||||||
|
g_debug("diya_virtual_keyboard_widget_init: Create new widget");
|
||||||
|
GtkLayoutManager *grid_layout = gtk_widget_get_layout_manager(GTK_WIDGET(self));
|
||||||
|
// gtk_orientable_set_orientation(GTK_ORIENTABLE(grid_layout), GTK_ORIENTATION_VERTICAL);
|
||||||
|
gtk_grid_layout_set_row_spacing(GTK_GRID_LAYOUT(grid_layout), 2);
|
||||||
|
gtk_grid_layout_set_column_spacing(GTK_GRID_LAYOUT(grid_layout), 2);
|
||||||
|
// gtk_grid_layout_set_baseline_row(GTK_GRID_LAYOUT(grid_layout), 4);
|
||||||
|
// init buttons
|
||||||
|
self->vkb = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_virtual_keyboard_widget_class_init(DiyaVirtualKeyboardWidgetClass *class)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
|
gobject_class->dispose = diya_virtual_keyboard_widget_dispose;
|
||||||
|
gtk_widget_class_set_css_name(GTK_WIDGET_CLASS(class), "diya-vkb");
|
||||||
|
gtk_widget_class_set_layout_manager_type(GTK_WIDGET_CLASS(class), GTK_TYPE_GRID_LAYOUT);
|
||||||
|
g_signal_new(DIYA_SIGNAL_VKB_KEY_PRESSED,
|
||||||
|
DIYA_TYPE_VKB_BUTTON,
|
||||||
|
G_SIGNAL_DETAILED |
|
||||||
|
G_SIGNAL_ACTION |
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
g_signal_new(DIYA_SIGNAL_VKB_KEY_RELEASED,
|
||||||
|
DIYA_TYPE_VKB_BUTTON,
|
||||||
|
G_SIGNAL_DETAILED |
|
||||||
|
G_SIGNAL_ACTION |
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_vkb_widget_on_key_pressed(DiyaVkbButton* button, DiyaVirtualKeyboardWidget* self)
|
||||||
|
{
|
||||||
|
gtk_widget_add_css_class(GTK_WIDGET(button), "active");
|
||||||
|
diya_virtual_keyboard_send_key(self->vkb, button->key,VKB_KEY_STATE_PRESSED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_vkb_widget_on_key_released(DiyaVkbButton* button, DiyaVirtualKeyboardWidget* self)
|
||||||
|
{
|
||||||
|
if(!diya_vkb_key_is_modifier(button->key))
|
||||||
|
{
|
||||||
|
gtk_widget_remove_css_class(GTK_WIDGET(button), "active");
|
||||||
|
}
|
||||||
|
diya_virtual_keyboard_send_key(self->vkb, button->key,VKB_KEY_STATE_RELEASED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_kb_modifier_changed(DiyaVirtualKeyboard* kb, DiyaVkbButton* button)
|
||||||
|
{
|
||||||
|
if(!diya_virtual_keyboard_key_modifier_is_active(kb, button->key))
|
||||||
|
{
|
||||||
|
gtk_widget_remove_css_class(GTK_WIDGET(button), "active");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_virtual_keyboard_widget_set_keyboard(DiyaVirtualKeyboardWidget* self, DiyaVirtualKeyboard* keyboard)
|
||||||
|
{
|
||||||
|
self->vkb = keyboard;
|
||||||
|
int index = 0;
|
||||||
|
if (self->buttons)
|
||||||
|
{
|
||||||
|
GList *it = NULL;
|
||||||
|
for (it = self->buttons; it; it = it->next)
|
||||||
|
{
|
||||||
|
if (it->data)
|
||||||
|
{
|
||||||
|
DiyaVkbButton* button = it->data;
|
||||||
|
DiyaVkbKey *key = NULL;
|
||||||
|
if(button->mod_sig_id > 0)
|
||||||
|
{
|
||||||
|
g_signal_handler_disconnect(self->vkb,button->mod_sig_id);
|
||||||
|
button->mod_sig_id = 0;
|
||||||
|
}
|
||||||
|
if(keyboard)
|
||||||
|
{
|
||||||
|
key = diya_virtual_keyboard_get_key(self->vkb, g_vkb_layout[index]);
|
||||||
|
g_debug("set button key: %s", diya_object_to_string(key));
|
||||||
|
if(diya_vkb_key_is_modifier(key))
|
||||||
|
{
|
||||||
|
button->mod_sig_id = g_signal_connect(self->vkb, DIYA_SIGNAL_VKB_MODIFIER_CHANGED, G_CALLBACK(on_kb_modifier_changed), button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diya_vkb_button_set_key(button, key);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget *diya_virtual_keyboard_widget_new(DiyaVirtualKeyboard* keyboard)
|
||||||
|
{
|
||||||
|
DiyaVirtualKeyboardWidget *self = g_object_new(DIYA_TYPE_VIRTUAL_KEYBOARD_WIDGET, NULL);
|
||||||
|
GtkLayoutManager *grid_layout = gtk_widget_get_layout_manager(GTK_WIDGET(self));
|
||||||
|
self->vkb = keyboard;
|
||||||
|
if(self->vkb == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < VKB_N_CELLS; i++)
|
||||||
|
{
|
||||||
|
gboolean skip = false;
|
||||||
|
int row = VKB_ROW_NUM(i);
|
||||||
|
int col = VKB_COL_NUM(i);
|
||||||
|
switch (row)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
skip = (col % 2 != 0) || (col > 26);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
skip = (col == 1) || (col == 2) || (col != 0 && col % 2 == 0);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
skip = (col == 1) || (col == 2) || (col != 0 && col % 2 == 0) || (col > 25);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
skip = (col > 0 && col < 3) || (col != 0 && col % 2 == 0);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
skip = (col > 0 && col < 3) || (col == 4) || (col == 6) || (col > 7 && col < 19) || (col > 19 && col % 2 == 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skip)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget *button = GTK_WIDGET(diya_vkb_button_new(NULL));
|
||||||
|
self->buttons = g_list_append(self->buttons, button);
|
||||||
|
gtk_widget_set_parent(button, GTK_WIDGET(self));
|
||||||
|
gtk_widget_set_hexpand(button, true);
|
||||||
|
GtkGridLayoutChild *grid_child = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(grid_layout, button));
|
||||||
|
|
||||||
|
g_signal_connect(button, "pressed", G_CALLBACK(diya_vkb_widget_on_key_pressed),self);
|
||||||
|
g_signal_connect(button, "released", G_CALLBACK(diya_vkb_widget_on_key_released),self);
|
||||||
|
|
||||||
|
gtk_grid_layout_child_set_row(grid_child, row);
|
||||||
|
gtk_grid_layout_child_set_column(grid_child, col);
|
||||||
|
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 26:
|
||||||
|
case 29:
|
||||||
|
case 58:
|
||||||
|
case 87:
|
||||||
|
case 116:
|
||||||
|
gtk_grid_layout_child_set_column_span(grid_child, 3);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 83:
|
||||||
|
gtk_grid_layout_child_set_column_span(grid_child, 4);
|
||||||
|
break;
|
||||||
|
/* case 87:
|
||||||
|
gtk_grid_layout_child_set_column_span(grid_child, 5); */
|
||||||
|
break;
|
||||||
|
case 123:
|
||||||
|
gtk_grid_layout_child_set_column_span(grid_child, 12);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (i > 0)
|
||||||
|
gtk_grid_layout_child_set_column_span(grid_child, 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(keyboard)
|
||||||
|
{
|
||||||
|
diya_virtual_keyboard_widget_set_keyboard(self, keyboard);
|
||||||
|
}
|
||||||
|
return GTK_WIDGET(self);
|
||||||
|
}
|
20
src/widgets/virtual-keyboard-widgets.h
Normal file
20
src/widgets/virtual-keyboard-widgets.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef DIYA_VIRTUAL_KEYBOARD_WIDGETS_H
|
||||||
|
#define DIYA_VIRTUAL_KEYBOARD_WIDGETS_H
|
||||||
|
|
||||||
|
#include "shell.h"
|
||||||
|
#include "virtual-keyboard.h"
|
||||||
|
|
||||||
|
#define DIYA_TYPE_VIRTUAL_KEYBOARD_WIDGET (diya_virtual_keyboard_widget_get_type())
|
||||||
|
G_DECLARE_FINAL_TYPE (DiyaVirtualKeyboardWidget, diya_virtual_keyboard_widget, DIYA, VIRTUAL_KEYBOARD_WIDGET, GtkWidget)
|
||||||
|
|
||||||
|
GtkWidget* diya_virtual_keyboard_widget_new(DiyaVirtualKeyboard* keyboard);
|
||||||
|
void diya_virtual_keyboard_widget_set_keyboard(DiyaVirtualKeyboardWidget* widget, DiyaVirtualKeyboard* keyboard);
|
||||||
|
|
||||||
|
|
||||||
|
#define DIYA_TYPE_VKB_BUTTON (diya_vkb_button_get_type())
|
||||||
|
G_DECLARE_FINAL_TYPE (DiyaVkbButton, diya_vkb_button, DIYA, VKB_BUTTON, GtkWidget)
|
||||||
|
|
||||||
|
DiyaVkbButton* diya_vkb_button_new(DiyaVkbKey* key);
|
||||||
|
void diya_vkb_button_set_key(DiyaVkbButton* btn, DiyaVkbKey *key);
|
||||||
|
|
||||||
|
#endif
|
Reference in New Issue
Block a user