gtkD window centering message up and no app on taskbar
Johnson Jones via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Tue Aug 8 16:00:25 PDT 2017
On Tuesday, 8 August 2017 at 21:37:40 UTC, Mike Wey wrote:
> On 07-08-17 23:52, Johnson Jones wrote:
>> On Monday, 7 August 2017 at 20:57:08 UTC, Mike Wey wrote:
>>> On 07-08-17 22:46, Johnson Jones wrote:
>>>> [...]
>>>
>>> This appears to be a GTK issue, a work around might be to get
>>> the Window handle from gtk and use the Windows API to set the
>>> taskbar visibility.
>>>
>>
>> Yeah, I was thinking about that but haven't yet figured out
>> how to find the window handle ;/
>
> To get the Window handle you could use this for 32bit Windows:
>
> ```
> import gtk.c.functions;
>
> // Danger, Will Robinson!
>
> HANDLE handle =
> *(cast(HANDLE*)((cast(void*)gtk_widget_get_window(w.getWidgetStruct()))+4));
>
>
> ```
> Where w is your application window, i used this in the map
> event signal so the handle is actually set. To complicate
> things there is a race condition in gdk some ware so at random
> the handle isn't valid.
>
>
> I haven't been able to set the taskbar icon with is tough.
>
> The two attempts:
>
> -Setting the parent window to null as windows with no parent
> should have an taskbar icon:
>
> ```
> ShowWindow(handle, SW_HIDE);
> SetParent(handle, null);
> ShowWindow(handle, SW_SHOW);
> ```
>
> Or set the extended window style to WS_EX_APPWINDOW as that
> should fore an taskbar icon according to msdn.
>
> ```
> ShowWindow(handle, SW_HIDE);
> SetWindowLong(handle, GWL_EXSTYLE, WS_EX_APPWINDOW);
> ShowWindow(handle, SW_SHOW);
> ```
Yeah, they keep returning null or some integer < 100(probably
junk values).
There surely has to be a way to get the windows handle? We could
use Win32 api and "search" for the window and get the handle but
that isn't that safe unless we can specify the windows classname
or title uniquely.
Things like ispy can find windows by coordinates but I think they
essentially use the above methods and region compares. e.g.,
there is no FindWindowByCoordinates... which still wouldn't be
very accurate.
// Fixup missing taskbar icon
void SetTaskBarIcon(gtk.ApplicationWindow window)
{
version(Windows)
version(X86)
{
import core.sys.windows.winuser, gdk.Window;
auto x = window.getWidgetStruct();
auto y =
((cast(void*)gtk.gtk_widget_get_window(window.getWidgetStruct()))+4);
auto handle =
*(cast(core.sys.windows.winuser.HANDLE*)((cast(void*)gtk.gtk_widget_get_window(window.getWidgetStruct()))+4));
ShowWindow(handle, SW_HIDE);
SetParent(handle, null);
SetWindowLong(handle, GWL_EXSTYLE, WS_EX_APPWINDOW);
ShowWindow(handle, SW_SHOW);
}
return;
}
Sometimes I get y = 4, which I think is what you were saying
before. Sometimes I get handle = < 100.
I've tried in a few places but not after Main.run(), which maybe
is needed for gtk to register the window and all that? I guess I
can run that function in a callback and see if it is valid...
Didn't work.
I can't really find anything on line about getting a windows
handle from gtk ;/
There is this:
https://stackoverflow.com/questions/23021327/how-i-can-get-drawingarea-window-handle-in-gtk3
Gdk.threads_enter()
#get the gdk window and the corresponding c gpointer
drawingareawnd = drawingarea.get_property("window")
#make sure to call ensure_native before e.g. on realize
if not drawingareawnd.has_native():
print("Your window is gonna freeze as soon as you
move or resize it...")
ctypes.pythonapi.PyCapsule_GetPointer.restype =
ctypes.c_void_p
ctypes.pythonapi.PyCapsule_GetPointer.argtypes =
[ctypes.py_object]
drawingarea_gpointer =
ctypes.pythonapi.PyCapsule_GetPointer(drawingareawnd.__gpointer__, None)
#get the win32 handle
gdkdll = ctypes.CDLL ("libgdk-3-0.dll")
hnd =
gdkdll.gdk_win32_window_get_handle(drawingarea_gpointer)
#do what you want with it ... I pass it to a gstreamer
videosink
Gdk.threads_leave()
which suggests that maybe gdk_win32_window_get_handle can be used
Ok, I was able to get it to work using that code. I had to do
some wonky dll imports and stuff but that function seems to be
the correct one. I could not use it until after the window was
created(I used it in a button handler), else it crashed the app
for some reason.
import core.sys.windows.winuser, gdk.Window;
auto handle =
cast(core.sys.windows.winuser.HANDLE)gdk_win32_window_get_handle(gtk.gtk_widget_get_window(window.getWidgetStruct()));
ShowWindow(handle, SW_HIDE);
SetParent(handle, null);
SetWindowLong(handle, GWL_EXSTYLE, WS_EX_APPWINDOW);
ShowWindow(handle, SW_SHOW);
Seems to work.
So you might want to add gdk_win32_window_get_handle as an export
in gtkD so it can be used easier.
The full code is:
void SetTaskBarIcon(gtk.ApplicationWindow window)
{
version(Windows)
version(X86)
{
import core.sys.windows.winuser, gdk.Window;
auto handle =
cast(core.sys.windows.winuser.HANDLE)gdk_win32_window_get_handle(gtk.gtk_widget_get_window(window.getWidgetStruct()));
ShowWindow(handle, SW_HIDE);
SetParent(handle, null);
SetWindowLong(handle, GWL_EXSTYLE, WS_EX_APPWINDOW);
ShowWindow(handle, SW_SHOW);
}
return;
}
Probably could be designed better. If I use it like
MainWindow.addOnShow((Widget widget) {
MainWindow.SetTaskBarIcon(); });
the window never shows and a lot of gtk errors are given about
updating the window.
(test.exe:4440): Gdk-WARNING **: gdkwindow-win32.c:439:
UpdateLayeredWindow failed with code 87: The parameter is
incorrect.
which comes from this line:
SetWindowLong(handle, GWL_EXSTYLE, WS_EX_APPWINDOW);
So maybe we have to GetWindowLong and modify it slightly
SetWindowLong(handle, GWL_EXSTYLE, GetWindowLong(handle,
GWL_EXSTYLE) | WS_EX_APPWINDOW);
which doesn't work. The error is no longer their but the icon
doesn't show up.
But, finally, this does seem to work:
// Fixup missing taskbar icon
void SetTaskBarIcon(gtk.ApplicationWindow window)
{
version(Windows)
version(X86)
{
import core.sys.windows.winuser, gdk.Window;
auto handle =
cast(core.sys.windows.winuser.HANDLE)gdk_win32_window_get_handle(gtk.gtk_widget_get_window(window.getWidgetStruct()));
ShowWindow(handle, SW_HIDE);
// SetParent(handle, null);
SetWindowLong(handle, GWL_EXSTYLE, GetWindowLong(handle,
GWL_EXSTYLE) | WS_EX_APPWINDOW);
ShowWindow(handle, SW_SHOW);
}
return;
}
Of course, along with this:
MainWindow.addOnShow((Widget widget) {
MainWindow.SetTaskBarIcon(); });
More information about the Digitalmars-d-learn
mailing list