summaryrefslogtreecommitdiffhomepage
path: root/src/console/ptyc_console_poller.c
blob: 2d7e9c031ff0238a4ce8f26b395b2ad4f5e58a7b (plain)
1
2
3
4
5
6
7
8
9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*********************************************************/
/*  ptycon: a pty-console bridge                         */
/*  Copyright (C) 2016--2017  SysDeer Technologies, LLC  */
/*  Released under GPLv2 and GPLv3; see COPYING.PTYCON.  */
/*********************************************************/

#include <psxtypes/psxtypes.h>
#include <ntcon/ntcon.h>
#include <ntapi/ntapi.h>
#include <gdi/gdi.h>

#include <ptycon/ptycon.h>
#include "ptycon_driver_impl.h"

int __stdcall ptyc_console_poller(struct ptyc_driver_ctx_impl * ictx)
{
	int32_t				status;
	int32_t				iostatus;
	struct ptyc_term_ctx *		tctx;
	struct ptyc_driver_ctx *	dctx;
	nt_tty_sigctl_info		ctlinfo;
	void *				hwnd;
	void *				hevent;
	nt_timeout			timeout;
	nt_iosb				iosb;
	gdi_rect			orect;
	gdi_rect			crect;
	int				diff;

	tctx = &ictx->tctx;
	dctx = &ictx->ctx;

	if (!(hwnd = ntcon->get_console_window()))
		return NT_STATUS_INTERNAL_ERROR;

	if ((status = ntapi->tt_create_private_event(
			&hevent,
			NT_NOTIFICATION_EVENT,
			NT_EVENT_NOT_SIGNALED)))
		return status;

	if (!(gdi->get_client_rect(
			hwnd,
			&orect)))
		return NT_STATUS_INTERNAL_ERROR;

	timeout.quad = (-1) * 10 * 1000 * 50;

	do {
		status = ntapi->zw_wait_for_single_object(
			hevent,
			NT_SYNC_ALERTABLE,
			&timeout);

		if (!(gdi->get_client_rect(
				hwnd,
				&crect)))
			return NT_STATUS_INTERNAL_ERROR;

		diff = (crect.right-crect.left !=orect.right-orect.left)
			|| (crect.bottom-crect.top !=orect.bottom-orect.top);

		if (diff) {
			orect.left   = crect.left;
			orect.right  = crect.right;
			orect.top    = crect.top;
			orect.bottom = crect.bottom;

			if (!(ntcon->get_console_screen_buffer_info(
					tctx->hout,
					&tctx->screen_info)))
				return NT_STATUS_INTERNAL_ERROR;

			ntapi->tt_aligned_block_memset(
				&ctlinfo,0,sizeof(ctlinfo));

			ctlinfo.winsize.ws_col = tctx->screen_info.window.right
						 - tctx->screen_info.window.left
						 + 1;

			ctlinfo.winsize.ws_row = tctx->screen_info.window.bottom
						 - tctx->screen_info.window.top
						 + 1;

			if ((iostatus = ntapi->pty_ioctl(
					ictx->cctx.hptm,
					0,0,0,
					&iosb,
					TTY_TIOCSWINSZ,
					&ctlinfo,sizeof(ctlinfo),
					&ctlinfo,sizeof(ctlinfo))))
				return iostatus;
		}
	} while ((status == NT_STATUS_TIMEOUT) && (dctx->status == NT_STATUS_SUCCESS));

	return (dctx->status == NT_STATUS_PIPE_DISCONNECTED)
		? NT_STATUS_SUCCESS
		: dctx->status ? dctx->status : status;
}