wxWidgets dark mode on macOS - c++

According to the release notes for 3.1.3 (https://raw.githubusercontent.com/wxWidgets/wxWidgets/v3.1.3/docs/changes.txt) dark mode support has been added to wxWidgets for Mojave+.
For the documentation for wxSysColourChanged, it still states that this is for Windows only but I thought the dark mode support for macOS should include this too? Dark mode is only a recent addition to Windows UWP apps and not Win32 (see dark mode on Windows 10 for a discussion of that on the forum).
In any case I cannot get the event to fire, although switching to dark mode does indeed correctly update the GUI elements eg. wxlistctrl and wxbutton without me having to manually enforce colour changes.
I am trying to capture the system colour change event so that I can manually redraw my own "owner-drawn" custom GUI elements correctly dark/light.
I hook up the Bind in the constructor to my event but nothing works:
Bind(wxEVT_SYS_COLOUR_CHANGED, &myFrame::OnSystemColourChanged, this);
void myFrame::OnSystemColourChanged(wxSysColourChangedEvent &event)
{
wxSystemAppearance s = wxSystemSettings::GetAppearance();
wxString dark = s.IsDark() ? "it's dark" : "it's light";
wxString m("System colour changed - ");
m += dark;
::wxMessageBox(m);
event.Skip();
}
I have got this open as a query on the forum (here) and they recommended the mailing list but I notice that wxWidgets questions are quickly addressed on here, particularly by VZ so here's hoping!
Am I missing some method of detecting colour changes?

OK, I managed to get the code to hit. I debugged it by adding a wxApp-level HandleEvent override function to see what events were being handled by the application (yes all events go through here):
void myApp::HandleEvent(wxEvtHandler *handler, wxEventFunction func, wxEvent& event) const
{
wxApp::HandleEvent(handler, func, event);
}
wxSysColourChanged events are indeed passing through this.
I managed to get my main frame's handler to hit by hooking up differently. Instead of
Bind(wxEVT_SYS_COLOUR_CHANGED, &myFrame::OnSystemColourChanged, this);
I used this instead:
Bind(wxEVT_SYS_COLOUR_CHANGED, wxSysColourChangedEventHandler(myFrame::OnSystemColourChanged), this);
I have no idea why &myFrame::OnSystemColourChanged wouldn't be recognised.
Also, I could not get any message boxes to show up in my event handler. ::wxMessageBox and wxMessageDialog did not show. cout output did show up but no popup GUI dialogs.
I am not going to be showing message boxes in this handler anyway so it isn't a problem but was trying to show a message for debugging/testing purposes.

Related

C++: Need to toggle a switch to get dynamic resizeEvent() data in my Qt5 Window!? (Linux, X11)

Iv'e been trying now for two days to just get a setup working for when I resize my QMainWindow in the QT5 program I'm working in. I have been starting to add my own X11 code in but it's starting to feel ridiculous basically duplicating functionality that should be in there.
Then I just had a search in youtube and there's someone showing that it indeed should work what I'm trying to do.
Basically I just want to get a stream of events that return the updated window size and position. Overriding the resizeEvent() and moveEvent() were the first things I tried but I only get an event triggered once I let go of the mouse. Not while I'm drag-scaling the window.
I have tried many things.
I'm starting to wonder if that's just not Working on Linux, or Raspbian Buster actually?
Or is there a setting that I need to toggle to get dynamic events? Is there some kind of 'performance mode' or something? I'm using Qt5.12
void StreamWindow::resizeEvent(QResizeEvent* event)
{
QSize size = event->size();
printf("Size: %d, %d\n", size.width(), size.height());
// HERE I'm planning to do stuff
QMainWindow::resizeEvent(event);
}
Thanks!

wxFrame and wxTaskBarIcon taskbar event Mac OSX : callback not being triggered

I have a derived class for wxFrame (MyFrame) (for OSX - Yosemite platform), where it calls:
Bind(wxEVT_TASKBAR_RIGHT_DOWN), &HandleTaskBarEvent, this);
The issue is HandleTaskBarEvent is not being invoked when I right click the icon in the dock.
I see the generic right click menu that Mac has (Open at Login, Keep in Dock, etc) for the main icon in the dock.
Also, I created a wxTaskBarIcon. I am guessing this will be utilized for the minimized icon in the dock after the frame is minimized.
systemIcon = new wxTaskBarIcon(); //declared in header
systemIcon.Bind(wxEVT_TASKBAR_RIGHT_DOWN, &HandleTaskBarEvent, this);
Popup = new wxMenu(); //declared in header
QuitMenu = new wxMenuItem(Popup, wxID_ANY, wxString(wxT("Quit")), wxEmptyString, wxITEM_NORMAL); //declared in header
Popup->Append(QuitMenu)
Popup->Bind(wxEVT_COMMAND_MENU_SELECTED, &CloseFunc, this, QuitMenu->GetId());
This is inside the same derived class(MyFrame).
I call Iconize() inside that MyFrame same function, which works as expected. It minimized the window.
This is the HandleTaskBarEvent function (virtual)
void MyFrame::HandleTaskBarEvent(wxTaskBarIconEvent& event)
{
if(event.GetEventType() == wxEVT_TASKBAR_RIGHT_DOWN)
{
systemIcon->PopupMenu(Popup);
}
}
I saw this post : Mouse Events of WxPython TaskBarIcon on Mac OSX are not triggering
and there seems to be a bug about it. But I am not able to find that bug or its status online. It is mentioned that the issue is with wxPython, but seems related to my problem.
Also I created a derived class for wxTaskBarIcon and overrode CreatePopupMenu and made systemIcon as an instance of MyTaskBarIcon, but that function is not being triggered for any clicks(left,right, etc). Also the main wxFrame 's Bind callback (HandleTaskBarEvent) is not being triggered, hence the systemIcon is not being able to popup the menu.
I am not using mouse for my Mac (using trackpad instead). Not sure if it should make any difference to right click code, but adding the information here anyways.
So I am thinking this could be wxWidget-OSX specific issue, because the code works on Windows as expected.
Does anyone know if this is purely wxWidget-OSX incomplete feature, if there is any open bugs about it, and more importantly if there is any solution to show the popup menu items for the minimized icon in the dock, and to handle the click events for the menu.
Thanks in advance.
This is a limitation of the OS X wxTaskBarIcon implementation. See wxTaskBarIcon on OSX - two-finger click does not send mouse event and related/linked issues.
The only way I know of (on OS X) is overriding wxTaskBarIcon::CreatePopupMenu().
You should be able to have something like:
MyApp::wxApp/
MyTaskBarIcon::wxTaskBarIcon (override CreatePopupMenu(), return a new wxMenu)
This is the model I use in a few applications and it works the same on Windows and OS X (albeit no specific click handlers as mentioned).

Onscreen Keyboard in Qt 5

I want to create a onscreen keyboard for a desktop application. The application will be built in Qt 5. I have couple of questions, please clarify them.
What is the replacement of QInputContext in Qt5? (Because I read somewhere about onscreen keybord by implementing QInputContext but this is not supported by Qt 5.)
Where can I find QPlatformInputContext and QInputPanel (on an internet search I found these two as alternatives of QInputContext but not sure about that and also I was unable to find them)?
My requirements:
Keyboard will not use QML or any external library (already build other keyboards).
Keyboard will use Qt Gui (traditional).
I understand there are two challenges you would have:
Getting notified as to when to show/hide the on-screen keyboard, based on the focus being on text widgets
How to post key-press event to the text widgets
ANSWER
As for the former, you could use QObject::InstallEventFilter() on widgets that you want to provide the keyboard service to. You can then look for the mouseReleaseEvent along the lines of the Qt code in the link.
This can be achieved by using QCoreApplication::postEvent()
As for QPlatformInputContext, get the example of a Qt Virtual Keyboard here.
I took me quite a while to find out how to do this in QT5 without qml and too much work. So thought I'd share:
#include <QCoreApplication>
#include <QGuiApplication>
#include <QKeyEvent>
void MainWindow::on_pushButton_clicked()
{
Qt::Key key = Qt::Key_1;;
QKeyEvent pressEvent = QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier, QKeySequence(key).toString());
QKeyEvent releaseEvent = QKeyEvent(QEvent::KeyRelease, key, Qt::NoModifier);
QCoreApplication::sendEvent(QGuiApplication::focusObject(), &pressEvent);
QCoreApplication::sendEvent(QGuiApplication::focusObject(), &releaseEvent);
}
The clue here is that by clicking buttons (if you would manually make your keyboard), launches a sendevent to the current object thas has focus (for example a textbox). You could of course hardcode a textbox, but that only works if you have only a single input to use your keyboard for.
The last thing you have to make sure, is to set the focusPolicy of your keyboard buttons to NoFocus, to prevent focus from shifting when the keyboard is pressed.
Credits go to https://www.wisol.ch/w/articles/2015-07-26-virtual-keyboard-qt/
Hope this helps someone.
A good example is given in here http://tolszak-dev.blogspot.com.tr/2013/04/qplatforminputcontext-and-virtual.html
uses Qt Quick for on screen keyboard.
You can check it.
I just got this working in my awesome Qt app. Here is how I did it.
For Android and iOS:
QObject::connect(lineEdit, SIGNAL(returnPressed()), qApp->inputMethod(), SLOT(hide()));
For iOS:
Subclass QLineEdit and add the following:
void focusOutEvent(QFocusEvent * fe)
{
QLineEdit::focusOutEvent(fe);
#ifdef Q_OS_IOS
if(fe->reason() == Qt::OtherFocusReason)
{
// Done was pressed!
emit returnPressed();
}
#endif
}
Btw, the QInputMethod docs don't say much about how to access it from c++. You have to get an instance from QGuiApplication, like I did above.
Hope that helps.
Qt now provides a virtual keyboard framework in Qt 5.5.
http://doc.qt.io/QtVirtualKeyboard/
I have not tried it, so I can't say how easy it is to use. It looks like it's QML-based.
(It says it's for Linux and boot2qt, but it can also be built for Windows according to the building page (http://doc.qt.io/QtVirtualKeyboard/build.html))

Gtkmm 3.0 How to switch between frames or windows

I'm rather new to C++, I have a bit of experience with MCV programming in Java. im using GTKmm on C++
What I'm trying to do is writing an application for teaching assistants to submit and edit applications to various positions, and administrators to come in view, and accept these applications.
What I'm trying to do at the begging is create 3 'frames' (I'm working on the submitting application for students only at the moment)
This first will have 2 buttons 1 for selecting if you're a student/admin
Upon clicking you're a student I want to hide this frame and show my second frame
The second frame will have another 2 buttons one for creating an application, and the other for editing applications
My core problem is that I don't understand how to switch between the frames, I've written all the code for my Model, and understand everything I want it to do however I cant seem to find how to do this...
My only idea would be to create windows for each of these, make them look all nice w/e, then when a button is pressed have that window close and a string written to file I can access to see which button has been pressed, then open a new window accordingly. Should I do it like this or is there a better way?
I think I can suggest a better/more idiomatic option for any version >= GTK+ 3.10 - which, to be fair, arrived about half a year after the accepted answer.
If you want to switch between widgets one-at-a-time without any accessories like tabs, then a Gtk::Stack seems like a better option. Because it's specifically geared for one-at-a-time presentation, without any redundancy and (theoretical) overhead from a Notebook's manual tabbing features, which you'd just be disabling straight away! It's a container with multiple children, with one visible at any given moment, and of course methods to change the active child.
You can hook up your own widgets and/or events to manage which of the Stack's children is shown. Alternatively - albeit possibly just restoring the redundancy in this case - there's a StackSwitcher companion widget, which is pretty much a vertical tab-bar as seen in the GTK+ demo and GNOME Tweak Tool.
Easiest way is to use a Notebook widget. You can hide the tabs since you will be controlling which page is showing, using method set_show_tabs(false). Put the top level widget for each of your frames in a pane using method append_page(), and switch between them using set_current_page(). You might want to hide the notebook's bevel if it's distracting, using method set_show_bevel(false).
Use signals to make a widget (e.g. "I'm a student" button) on one page do something (e.g. go to the second page). If you don't know what this means or how to do it, go through the gtkmm tutorial, it will explain this and more.
A bit too late ! But here is my try :
Gtk::Notebook is great but it is not ideal in switching between app frames on menu item clicks. Gtk::Stack, since gtkmm 3.10, exists to mitigate this. Assuming you're using glade and Gtk::Builder :
class
class AppName : public Gtk::ApplicationWindow
{
public:
//...Your app methods and callbacks
void on_mb_itemname_selected(); // The call back for our menu item click/select
private:
//Builder which will help build the app from a .glade file
Glib::RefPtr<Gtk::Builder> _builder;
//...
//Your menu item to activate a particular frame
Gtk::MenuItem * _mb_itemname;
//Your handle to Gtk::Stack which is usually the stack for the whole app
Gtk::Stack * _app_stack;
//...
}
constructor
AppName::AppName(BaseObjectType *cobj,
Glib::RefPtr<Gtk::Builder>& ref_builder)
:Gtk::ApplicationWindow(cobj),_builder(ref_builder)
{
//.. Other setup
_builder->get_widget("your_glade_id_to_stack",_app_stack);
_builder->get_widget("your_glade_id_to_menu_item",_mb_itemname);
// Connect signal_select of our menu item to appropriate signal handler.
mb_itemname->signal_select().connect(
sigc::mem_fun(*this,&AppName::on_mb_itemname_selected));
}
our callback
void AppName::on_mb_itemname_selected()
{
// Change the visible child of the stack concerned.
Gtk::StackTransitionType ttype = STACK_TRANSITION_TYPE_NONE;
_app_stack->set_visible_child("your_widget_name",ttype);
// Note that widget name is not widget glade id.
// You can set your widget under name Packing -> Name
return;
}

How to create a non-interactive window in MFC

In my application I have a window which I popup with small messages on it (think similar to tooltip). This window uses the layered attributes to draw alpha backgrounds etc.
If I have several of these windows open at once, and I click one with my mouse, when they disappear they cause my application to lose focus (it switches focus to the app behind the current one).
How do I stop any interaction in my window?
It works because OnSetFocus (like many of the On* methods) gives you a chance to pre-empt an action before it actually occurs. The focus never actually switches to your non-interactive window.
After playing with the WM_NCACTIVATE message with no luck, I overrode the WM_SETFOCUS message:
void CMyWindow::OnSetFocus(CWnd* pOldWnd)
{
if (pOldWnd != NULL)
{
pOldWnd->SetFocus();
}
}
That seems to do the trick. No idea why it works though! Comments welcome on that issue.