summaryrefslogtreecommitdiff
path: root/tipper/message_pump.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tipper/message_pump.cpp')
-rw-r--r--tipper/message_pump.cpp201
1 files changed, 201 insertions, 0 deletions
diff --git a/tipper/message_pump.cpp b/tipper/message_pump.cpp
new file mode 100644
index 0000000..d891a33
--- /dev/null
+++ b/tipper/message_pump.cpp
@@ -0,0 +1,201 @@
+#include "common.h"
+#include "message_pump.h"
+#include "popwin.h"
+#include "options.h"
+
+HMODULE hUserDll;
+BOOL (WINAPI *MySetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD) = 0;
+BOOL (WINAPI *MyAnimateWindow)(HWND hWnd,DWORD dwTime,DWORD dwFlags) = 0;
+
+//DWORD message_pump_thread_id = 0;
+unsigned int message_pump_thread_id = 0;
+HANDLE hMPEvent;
+
+//DWORD CALLBACK MessagePumpThread(LPVOID param) {
+unsigned int CALLBACK MessagePumpThread(void *param) {
+ if(param) SetEvent((HANDLE)param);
+
+ CallService(MS_SYSTEM_THREAD_PUSH, 0, 0);
+
+ HWND hwndTip = 0;
+
+ MSG hwndMsg = {0};
+ while(GetMessage(&hwndMsg, 0, 0, 0) > 0 && !Miranda_Terminated()) {
+ if(!IsDialogMessage(hwndMsg.hwnd, &hwndMsg)) {
+ switch(hwndMsg.message) {
+ case MUM_CREATEPOPUP:
+ {
+ if(hwndTip) DestroyWindow(hwndTip);
+ // if child of clist, zorder is right, but it steals the first click on a contact :(
+
+ // copy topmost exstyle from clist, since we'll put clist under tip in WM_CREATE message
+ //LONG clist_exstyle = GetWindowLong((HWND)CallService(MS_CLUI_GETHWND, 0, 0), GWL_EXSTYLE);
+ //hwndTip = CreateWindowEx((clist_exstyle & WS_EX_TOPMOST), POP_WIN_CLASS, _T("TipperPopup"), WS_POPUP, 0, 0, 0, 0, 0/*(HWND)CallService(MS_CLUI_GETHWND, 0, 0)*/, 0, hInst, (LPVOID)hwndMsg.lParam);
+
+ hwndTip = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TOPMOST, POP_WIN_CLASS, _T("TipperPopup"), WS_POPUP, 0, 0, 0, 0, 0/*(HWND)CallService(MS_CLUI_GETHWND, 0, 0)*/, 0, hInst, (LPVOID)hwndMsg.lParam);
+ if(hwndMsg.lParam) free((LPVOID)hwndMsg.lParam);
+ }
+ break;
+
+ case MUM_DELETEPOPUP:
+ {
+ if(hwndTip) {
+ DestroyWindow(hwndTip);
+ hwndTip = 0;
+ }
+ }
+ break;
+ case MUM_GOTSTATUS:
+ {
+ if(hwndTip) SendMessage(hwndTip, PUM_SETSTATUSTEXT, hwndMsg.wParam, hwndMsg.lParam);
+ else if(hwndMsg.lParam) free((void *)hwndMsg.lParam);
+ }
+ break;
+ case MUM_GOTAVATAR:
+ {
+ if(hwndTip) SendMessage(hwndTip, PUM_SETAVATAR, hwndMsg.wParam, hwndMsg.lParam);
+ }
+ break;
+ default:
+ {
+ TranslateMessage(&hwndMsg);
+ DispatchMessage(&hwndMsg);
+ }
+ break;
+ }
+ }
+ }
+
+ CallService(MS_SYSTEM_THREAD_POP, 0, 0);
+
+ return 0;
+}
+
+void PostMPMessage(UINT msg, WPARAM wParam, LPARAM lParam) {
+ PostThreadMessage(message_pump_thread_id, msg, wParam, lParam);
+}
+
+// given a popup data pointer, and a handle to an event, this function
+// will post a message to the message queue which will set the hwnd value
+// and then set the event...so create an event, call this function and then wait on the event
+// when the event is signalled, the hwnd will be valid
+void FindWindow(POPUPDATAW *pd, HANDLE hEvent, HWND *hwnd);
+
+void InitMessagePump() {
+ WNDCLASS popup_win_class = {0};
+ popup_win_class.style = 0;
+ popup_win_class.lpfnWndProc = PopupWindowProc;
+ popup_win_class.hInstance = hInst;
+ popup_win_class.lpszClassName = POP_WIN_CLASS;
+ popup_win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
+ RegisterClass(&popup_win_class);
+
+ hUserDll = LoadLibrary(_T("user32.dll"));
+ if (hUserDll) {
+ MySetLayeredWindowAttributes = (BOOL (WINAPI *)(HWND,COLORREF,BYTE,DWORD))GetProcAddress(hUserDll, "SetLayeredWindowAttributes");
+ MyAnimateWindow=(BOOL (WINAPI*)(HWND,DWORD,DWORD))GetProcAddress(hUserDll,"AnimateWindow");
+ }
+
+ hMPEvent = CreateEvent(0, TRUE, 0, 0);
+ CloseHandle((HANDLE)_beginthreadex(0, 0, MessagePumpThread, hMPEvent, 0, &message_pump_thread_id));
+ WaitForSingleObject(hMPEvent, INFINITE);
+ CloseHandle(hMPEvent);
+}
+
+void DeinitMessagePump() {
+ PostMPMessage(WM_QUIT, 0, 0);
+
+ FreeLibrary(hUserDll);
+
+ UnregisterClass(POP_WIN_CLASS, hInst);
+}
+
+int ShowTip(WPARAM wParam, LPARAM lParam) {
+ CLCINFOTIP *clcit = (CLCINFOTIP *)lParam;
+ if(clcit->isGroup) return 0; // no group tips (since they're pretty useless)
+ if(clcit->isTreeFocused == 0 && options.show_no_focus == false) return 0;
+
+ CLCINFOTIPEX *clcit2 = (CLCINFOTIPEX *)malloc(sizeof(CLCINFOTIPEX));
+ memcpy(clcit2, clcit, sizeof(CLCINFOTIP));
+ clcit2->cbSize = sizeof(CLCINFOTIPEX);
+ clcit2->proto = 0;
+ clcit2->text = 0;
+
+ if(wParam) { // wParam is char pointer containing text - e.g. status bar tooltip
+ int size = MultiByteToWideChar(code_page, 0, (char *)wParam, -1, 0, 0);
+ if(size) {
+ clcit2->text = (wchar_t *)malloc(size * sizeof(wchar_t));
+ MultiByteToWideChar(code_page, 0, (char *)wParam, -1, clcit2->text, size);
+ GetCursorPos(&clcit2->ptCursor); // cursor pos broken?
+ }
+ }
+
+ PostMPMessage(MUM_CREATEPOPUP, 0, (LPARAM)clcit2);
+ return 1;
+}
+
+int ShowTipW(WPARAM wParam, LPARAM lParam) {
+ CLCINFOTIP *clcit = (CLCINFOTIP *)lParam;
+ if(clcit->isGroup) return 0; // no group tips (since they're pretty useless)
+ if(clcit->isTreeFocused == 0 && options.show_no_focus == false) return 0;
+
+ CLCINFOTIPEX *clcit2 = (CLCINFOTIPEX *)malloc(sizeof(CLCINFOTIPEX));
+ memcpy(clcit2, clcit, sizeof(CLCINFOTIP));
+ clcit2->cbSize = sizeof(CLCINFOTIPEX);
+ clcit2->proto = 0;
+ clcit2->text = 0;
+
+ if(wParam) { // wParam is char pointer containing text - e.g. status bar tooltip
+ clcit2->text = _tcsdup((TCHAR *)wParam);
+ GetCursorPos(&clcit2->ptCursor); // cursor pos broken?
+ }
+
+ PostMPMessage(MUM_CREATEPOPUP, 0, (LPARAM)clcit2);
+ return 1;
+}
+
+int HideTip(WPARAM wParam, LPARAM lParam) {
+ //CLCINFOTIP *clcit = (CLCINFOTIP *)lParam;
+ PostMPMessage(MUM_DELETEPOPUP, 0, 0);
+ return 1;
+}
+
+int ProtoAck(WPARAM wParam, LPARAM lParam) {
+ ACKDATA *ack = (ACKDATA *)lParam;
+ char *szMsg = (char *)ack->lParam;
+ if(ack->type == ACKTYPE_AWAYMSG && ack->result == ACKRESULT_SUCCESS && szMsg) {
+ int size = MultiByteToWideChar(code_page, 0, szMsg, -1, 0, 0);
+ if(size > 1) {
+ wchar_t *msg = (wchar_t *)malloc(size * sizeof(wchar_t));
+ MultiByteToWideChar(code_page, 0, (char *) szMsg, -1, msg, size);
+ PostMPMessage(MUM_GOTSTATUS, (WPARAM)ack->hContact, (LPARAM)msg);
+ }
+ }
+ return 0;
+}
+
+int FramesShowSBTip(WPARAM wParam, LPARAM lParam) {
+ if(options.status_bar_tips) {
+ char *proto = (char *)wParam;
+
+ CLCINFOTIPEX *clcit2 = (CLCINFOTIPEX *)malloc(sizeof(CLCINFOTIPEX));
+ memset(clcit2, 0, sizeof(CLCINFOTIPEX));
+ clcit2->cbSize = sizeof(CLCINFOTIPEX);
+ clcit2->proto = proto; // assume static string
+ GetCursorPos(&clcit2->ptCursor);
+
+ PostMPMessage(MUM_CREATEPOPUP, 0, (LPARAM)clcit2);
+
+ return 1;
+ }
+ return 0;
+}
+
+int FramesHideSBTip(WPARAM wParam, LPARAM lParam) {
+ if(options.status_bar_tips) {
+ PostMPMessage(MUM_DELETEPOPUP, 0, 0);
+ return 1;
+ }
+ return 0;
+}
+