-
Notifications
You must be signed in to change notification settings - Fork 43
Language widget for panel #301
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Implemented IPC-client + language widget based on it |
|
@ammen99, better?)) |
|
Hi! I haven't checked the PR carefully yet but I suppose it should use UPD: also please fix the formatting. |
src/util/wf-shell-app.hpp
Outdated
| int inotify_css_fd; | ||
| wf::config::config_manager_t config; | ||
| zwf_shell_manager_v2 *wf_shell_manager = nullptr; | ||
| WayfireIPC *ipc = nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest making WayfireIPC a singleton so that it won't be initialized until needed.
I usually do it like this:
WayfireIPCdoesn't have a public ctor- has private
static std::weak_ptr<WayfireIPC> instance_ - has public
static std::shared_ptr<WayfireIPC> Instance()which simply returnsinstance_.lock() - has public
static std::shared_ptr<WayfireIPC> Open()(or something, maybe you will come up with a better name) which initialize theinstance_if it's expired
Instance() should be called in reload_widgets so that we don't close-and-open the socket on every reload.
Probably Lock() would be a better name for Instance(), but I would still call it Instance for consistency with existing singletons.
See https://github.com/WayfireWM/wf-shell/blob/master/src/panel/widgets/tray/watcher.hpp#L18-L31 and https://github.com/WayfireWM/wf-shell/blob/master/src/panel/panel.cpp#L268.
src/util/wf-ipc.hpp
Outdated
|
|
||
| class WayfireIPC | ||
| { | ||
| int socket_fd; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you considered using Gio's SocketClient instead of handling it manually? I believe it would simplify the code.
|
@WShad sorry for the delay, we were finishing the gtk4 port .. if you still have interest, please update this PR to gtk4 as well. |
|
@WShad thanks for your updates! I looked briefly over your PR, a few things that stood out to me:
|
|
Wow! Thanks for so fast feedback!)))
|
|
I will separate wayfire's json handling into a subproject and will let you know when it is ready for incorporating into your pr :) |
|
@WShad It was actually easier than I expected, here is the json wrapper itself: https://github.com/WayfireWM/wf-json Here is the Wayfire PR where it is used WayfireWM/wayfire#2892 |
src/panel/widgets/language.cpp
Outdated
| button.show(); | ||
|
|
||
| ipc->subscribe(this, {"keyboard-modifier-state-changed"}); | ||
| ipc->send("{\"method\":\"wayfire/get-keyboard-state\"}", [=] (json_t data) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find your design very interesting with this send and the callback for the response. One thing I am not very sure about however is this, what deregisters the callback if the WayfireLanguage class is destroyed while waiting for the reply?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find your design very interesting with this send and the callback for the response
Thanks! I'm glad to hear that)
what deregisters the callback if the WayfireLanguage class is destroyed while waiting for the reply?
Nice point. Didn't think about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One idea would be to somehow connect the full ipc->send() version with the IPC subscriber interface, then have the IPC subscriber interface deregister itself from the IPC socket automatically. This is what we do for signals in Wayfire itself. Maybe the implementation will give you some inspirations, but feel free to come up with a different idea if you have a better one :)
https://github.com/WayfireWM/wayfire/blob/master/src/api/wayfire/signal-provider.hpp
https://github.com/WayfireWM/wayfire/blob/8a3e1cae5beda079060d7c5725812bdc589a6ae3/src/core/object.cpp#L7-L59
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolved. Now widgets must have their own IPC clients, they deregister themselves and all replies to that clients will be safely ignored.
ammen99
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getting closer to perfection :) a few smaller items that i noticed, otherwise lgtm
src/util/wf-ipc.cpp
Outdated
| WayfireIPC::~WayfireIPC() | ||
| { | ||
| disconnect(); | ||
| LOGI("IPC destroyed"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i don't think we need this message in 'production' :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Disagree, but - ok
src/util/wf-ipc.cpp
Outdated
|
|
||
| while (connection->get_socket()->get_available_bytes() > 0) | ||
| { | ||
| received = input->read(&length, 4); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer to have length as a local variable, it is not some 'state' which needs to be preserved across method calls.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also instead of 4, consider using sizeof(length), that way I think it is way clearer why we read those bytes separately :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer to have length as a local variable, it is not some 'state' which needs to be preserved across method calls.
Will fix. Legacy of prev impl)
src/util/wf-ipc.cpp
Outdated
| received = input->read(&length, 4); | ||
| if (received == -1) | ||
| { | ||
| LOGE("Receive message length failed"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when we log errors, it would make sense to also indicate where they are coming from, for example: "Error in Wayfire IPC communication: failed to receive message length"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(also applies to all the other LOGE calls in this file / PR
src/util/wf-ipc.cpp
Outdated
|
|
||
| while (connection->get_socket()->get_available_bytes() > 0) | ||
| { | ||
| received = input->read(&length, 4); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another thing: when calling read(), I we are not guaranteed to get the full number of bytes we request. In particular, if we have a longer ipc message, I think read could stop in the middle, return just some part of the message. At least the underlying read() syscall works this way. Example of what Wayfire does to combat this: https://github.com/WayfireWM/wayfire/blob/9c427024e849b0c676184c1af3c82b38f1f8fb67/plugins/ipc/ipc.cpp#L171-L285
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't actually confirm that. I experimented a lot and this is a results:
- under the pressure of data socket can get buffer overflow, if not read frequent enough
- if n bites written - n bites can be read (not like in a tcp connection)
- if server lags on read or write - client disconnected immediately
Can't reproduce situation where was read less than was written.
Using this IPC for three months, fixed some bugs, have no problems.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- under the pressure of data socket can get buffer overflow, if not read frequent enough
That's exactly the issue! It can be that the buffer can only accommodate the message partially.
I mean in practice I expect this to not cause any issues, so maybe we could simply leave this as a TODO comment in the code and fix it when somebody actually complains.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In any case would be good to at least check what is going on, so instead of errorring on n_bytes_read == 0, we need to error on n_bytes_read != n_bytes_wanted
|
@WShad For the CI to work, I think you need to add cmake to the list of dependencies, or to install yyjson as a dependency so that we don't have to build it as a submodule. Also you'll need to fix the codestyle. Otherwise LGTM, good work! |
|
I don't understand... How? My action completed successfully, they are the same - how it even can be? |
|
@WShad I also find it hard to comprehend why it works on the one CI and not on the other, but my guess would be that you add the json submodule as a dependency only to the Line 14 in 57a68cb
I believe this will fix the CI issue. A note on uncrustify: we use a custom uncrustify to be consistent with Wayfire. Wayfire itself uses a custom uncrustify because uncrustify-git currently crashesh on Wayfire's codebase, plus it had some formatting bugs which I fixed in my fork ... At least however, the CI will give you a patch to apply so you don't have to set it up locally, see https://github.com/WayfireWM/wf-shell/actions/runs/20010484621/job/57379300256?pr=301#step:9:1 |
Exactly! And why i lost that dependency(?) - it compiles locally just fine, without explicitly included 'json'. Strange...
Got it Will compile now. |
ammen99
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM now, thanks a lot!
|
Does it support a language emoji? If not, would be very nice to have along with an option to either show:
|
Adds language widget displaying current keyboard layout language.
