Skip to content

Commit

Permalink
Add ResizedCallback and MovedCallback for Win & Linux.
Browse files Browse the repository at this point in the history
  • Loading branch information
Berrysoft authored and SteveSandersonMS committed Dec 23, 2019
1 parent 6998bc7 commit e61f89e
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 15 deletions.
10 changes: 10 additions & 0 deletions src/WebWindow.Native/Exports.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ extern "C"
instance->SetSize(width, height);
}

EXPORTED void WebWindow_SetResizedCallback(WebWindow* instance, ResizedCallback callback)
{
instance->SetResizedCallback(callback);
}

EXPORTED void WebWindow_GetScreenSize(WebWindow* instance, int* width, int* height)
{
instance->GetScreenSize(width, height);
Expand All @@ -115,6 +120,11 @@ extern "C"
instance->SetPosition(x, y);
}

EXPORTED void WebWindow_SetMovedCallback(WebWindow* instance, MovedCallback callback)
{
instance->SetMovedCallback(callback);
}

EXPORTED void WebWindow_SetTopmost(WebWindow* instance, int topmost)
{
instance->SetTopmost(topmost);
Expand Down
19 changes: 19 additions & 0 deletions src/WebWindow.Native/WebWindow.Linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ WebWindow::WebWindow(AutoString title, WebWindow* parent, WebMessageReceivedCall
g_signal_connect(G_OBJECT(_window), "destroy",
G_CALLBACK(+[](GtkWidget* w, gpointer arg) { gtk_main_quit(); }),
this);
g_signal_connect(G_OBJECT(_window), "size-allocate",
G_CALLBACK(+on_size_allocate),
this);
}
}

Expand Down Expand Up @@ -233,6 +236,13 @@ void WebWindow::SetSize(int width, int height)
gtk_window_resize(GTK_WINDOW(_window), width, height);
}

void on_size_allocate(GtkWidget* widget, GdkRectangle* allocation, gpointer self)
{
int width, height;
gtk_window_get_size(GTK_WINDOW(widget), &width, &height);
((WebWindow*)self)->InvokeResized(width, height);
}

void WebWindow::GetScreenSize(int* width, int* height)
{
GdkScreen* screen = gtk_window_get_screen(GTK_WINDOW(_window));
Expand All @@ -258,6 +268,15 @@ void WebWindow::SetPosition(int x, int y)
gtk_window_move(GTK_WINDOW(_window), x, y);
}

gboolean on_configure_event(GtkWidget* widget, GdkEvent* event, gpointer self)
{
if (event->type == GDK_CONFIGURE)
{
((WebWindow*)self)->InvokeMoved(event->configure.x, event->configure.y);
}
return FALSE;
}

void WebWindow::SetTopmost(bool topmost)
{
gtk_window_set_keep_above(GTK_WINDOW(_window), topmost ? TRUE : FALSE);
Expand Down
14 changes: 14 additions & 0 deletions src/WebWindow.Native/WebWindow.Windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,20 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
if (webWindow)
{
webWindow->RefitContent();
int width, height;
webWindow->GetSize(&width, &height);
webWindow->InvokeResized(width, height);
}
return 0;
}
case WM_MOVE:
{
WebWindow* webWindow = hwndToWebWindow[hwnd];
if (webWindow)
{
int x, y;
webWindow->GetPosition(&x, &y);
webWindow->InvokeMoved(x, y);
}
return 0;
}
Expand Down
8 changes: 8 additions & 0 deletions src/WebWindow.Native/WebWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ typedef char* AutoString;
typedef void (*ACTION)();
typedef void (*WebMessageReceivedCallback)(AutoString message);
typedef void* (*WebResourceRequestedCallback)(AutoString url, int* outNumBytes, AutoString* outContentType);
typedef void (*ResizedCallback)(int width, int height);
typedef void (*MovedCallback)(int x, int y);

class WebWindow
{
private:
WebMessageReceivedCallback _webMessageReceivedCallback;
MovedCallback _movedCallback;
ResizedCallback _resizedCallback;
#ifdef _WIN32
static HINSTANCE _hInstance;
HWND _hWnd;
Expand Down Expand Up @@ -65,10 +69,14 @@ class WebWindow
void SetResizable(bool resizable);
void GetSize(int* width, int* height);
void SetSize(int width, int height);
void SetResizedCallback(ResizedCallback callback) { _resizedCallback = callback; }
void InvokeResized(int width, int height) { if (_resizedCallback) _resizedCallback(width, height); }
void GetScreenSize(int* width, int* height);
unsigned int GetScreenDpi();
void GetPosition(int* x, int* y);
void SetPosition(int x, int y);
void SetMovedCallback(MovedCallback callback) { _movedCallback = callback; }
void InvokeMoved(int x, int y) { if (_movedCallback) _movedCallback(x, y); }
void SetTopmost(bool topmost);
void SetIconFile(AutoString filename);
};
Expand Down
68 changes: 54 additions & 14 deletions src/WebWindow/WebWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public class WebWindow
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Auto)] delegate void OnWebMessageReceivedCallback(string message);
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Auto)] delegate IntPtr OnWebResourceRequestedCallback(string url, out int numBytes, out string contentType);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate void InvokeCallback();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate void ResizedCallback(int width, int height);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate void MovedCallback(int x, int y);

const string DllName = "WebWindow.Native";
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern IntPtr WebWindow_register_win32(IntPtr hInstance);
Expand All @@ -37,10 +39,12 @@ public class WebWindow
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_SetResizable(IntPtr instance, int resizable);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_GetSize(IntPtr instance, out int width, out int height);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_SetSize(IntPtr instance, int width, int height);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_SetResizedCallback(IntPtr instance, ResizedCallback callback);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_GetScreenSize(IntPtr instance, out int width, out int height);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern uint WebWindow_GetScreenDpi(IntPtr instance);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_GetPosition(IntPtr instance, out int x, out int y);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_SetPosition(IntPtr instance, int x, int y);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_SetMovedCallback(IntPtr instance, MovedCallback callback);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_SetTopmost(IntPtr instance, int topmost);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] static extern void WebWindow_SetIconFile(IntPtr instance, string filename);

Expand Down Expand Up @@ -95,6 +99,14 @@ public WebWindow(string title, Action<WebWindowOptions> configure)
AddCustomScheme(schemeName, handler);
}

var onResizedDelegate = (ResizedCallback)OnResized;
_gcHandlesToFree.Add(GCHandle.Alloc(onResizedDelegate));
WebWindow_SetResizedCallback(_nativeWebWindow, onResizedDelegate);

var onMovedDelegate = (MovedCallback)OnMoved;
_gcHandlesToFree.Add(GCHandle.Alloc(onMovedDelegate));
WebWindow_SetMovedCallback(_nativeWebWindow, onMovedDelegate);

// Auto-show to simplify the API, but more importantly because you can't
// do things like navigate until it has been shown
Show();
Expand All @@ -103,6 +115,8 @@ public WebWindow(string title, Action<WebWindowOptions> configure)
~WebWindow()
{
// TODO: IDisposable
WebWindow_SetResizedCallback(_nativeWebWindow, null);
WebWindow_SetMovedCallback(_nativeWebWindow, null);
foreach (var gcHandle in _gcHandlesToFree)
{
gcHandle.Free();
Expand Down Expand Up @@ -265,8 +279,11 @@ public int Width
set
{
GetSize();
_width = value;
SetSize();
if (_width != value)
{
_width = value;
SetSize();
}
}
}

Expand All @@ -280,8 +297,11 @@ public int Height
set
{
GetSize();
_height = value;
SetSize();
if (_height != value)
{
_height = value;
SetSize();
}
}
}

Expand All @@ -294,12 +314,19 @@ public Size Size
}
set
{
_width = value.Width;
_height = value.Height;
SetSize();
if (_width != value.Width || _height != value.Height)
{
_width = value.Width;
_height = value.Height;
SetSize();
}
}
}

private void OnResized(int width, int height) => SizeChanged?.Invoke(this, new Size(width, height));

public event EventHandler<Size> SizeChanged;

private int _x;
private int _y;

Expand All @@ -317,8 +344,11 @@ public int Left
set
{
GetPosition();
_x = value;
SetPosition();
if (_x != value)
{
_x = value;
SetPosition();
}
}
}

Expand All @@ -332,8 +362,11 @@ public int Top
set
{
GetPosition();
_y = value;
SetPosition();
if (_y != value)
{
_y = value;
SetPosition();
}
}
}

Expand All @@ -346,12 +379,19 @@ public Point Location
}
set
{
_x = value.X;
_y = value.Y;
SetPosition();
if (_x != value.X || _y != value.Y)
{
_x = value.X;
_y = value.Y;
SetPosition();
}
}
}

private void OnMoved(int x, int y) => LocationChanged?.Invoke(this, new Point(x, y));

public event EventHandler<Point> LocationChanged;

public Size ScreenSize
{
get
Expand Down
3 changes: 2 additions & 1 deletion testassets/MyBlazorApp/Pages/WindowProp.razor
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
@inject WebWindow Window

<h1>Window properties</h1>
<button class="btn btn-primary" @onclick="StateHasChanged">Refresh</button>
<h2>Screen size</h2>
<p>Width: @Window.ScreenSize.Width, Height: @Window.ScreenSize.Height, DPI: @Window.ScreenDpi</p>
<h2>Window size</h2>
Expand Down Expand Up @@ -39,7 +40,7 @@
</div>
</form>
<h2>Icon</h2>
<div class="form-row">
<div>
<div class="col form-group">
<label for="inputIcon">Icon file</label>
<input type="text" class="form-control" id="inputIcon" @bind="@iconFilename" />
Expand Down

0 comments on commit e61f89e

Please sign in to comment.