Hi Alexandre,
This has missed the last two commits. Is this codes presence in shell32 really a blocking issue? If so then I'd note that quite a lot of people have problems caused by the lack of this patch (can't quit apps etc).
thanks -mike
On Sun, 2003-11-30 at 16:16, Mike Hearn wrote:
Hi,
This patch updates my system tray patch to work with the new atom interning code, fixes a few bugs and replaces the per-icon mutex with a global one. The critical section handling should therefore be much less broken now.
Yes, I know it should be in wineshell.exe but for now this will do, and the code can always be moved later.
thanks -mike
ChangeLog: Implement support for XEMBED based system trays
Index: dlls/shell32/systray.c
RCS file: /home/wine/wine/dlls/shell32/systray.c,v retrieving revision 1.24 diff -u -r1.24 systray.c --- dlls/shell32/systray.c 24 Oct 2003 04:23:37 -0000 1.24 +++ dlls/shell32/systray.c 30 Nov 2003 16:08:37 -0000 @@ -1,11 +1,11 @@ /*
- Systray
- System tray handling code (client side)
- Copyright 1999 Kai Morich kai.morich@bigfoot.de
- Copyright 1999 Kai Morich kai.morich@bigfoot.de
- Copyright 2003 Mike Hearn mike@theoretic.com
- Manage the systray window. That it actually appears in the docking
- area of KDE or GNOME is delegated to windows/x11drv/wnd.c,
- X11DRV_WND_DockWindow.
- This code creates a window with the WS_EX_TRAYWINDOW style. The actual
- environment integration code is handled inside the X11 driver.
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
@@ -42,7 +42,17 @@ #include "commctrl.h" #include "wine/debug.h"
-WINE_DEFAULT_DEBUG_CHANNEL(shell); +WINE_DEFAULT_DEBUG_CHANNEL(systray);
+static CRITICAL_SECTION systray_lock; +static CRITICAL_SECTION_DEBUG critsect_debug = +{
- 0, 0, &systray_lock,
- { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
0, 0, { 0, (DWORD)(__FILE__ ": system tray") }
+}; +static CRITICAL_SECTION systray_lock = { &critsect_debug, -1, 0, 0, 0, 0 };
typedef struct SystrayItem { HWND hWnd; @@ -51,12 +61,11 @@ struct SystrayItem *nextTrayItem; } SystrayItem;
-static SystrayItem *systray=NULL; -static int firstSystray=TRUE; /* defer creation of window class until first systray item is created */ +static SystrayItem *systray = NULL; +static int firstSystray = TRUE; /* defer creation of window class until first systray item is created */
static BOOL SYSTRAY_Delete(PNOTIFYICONDATAA pnid);
#define ICON_SIZE GetSystemMetrics(SM_CXSMICON) /* space around icon (forces icon to center of KDE systray area) */ #define ICON_BORDER 4 @@ -74,21 +83,26 @@ { HDC hdc; PAINTSTRUCT ps;
- TRACE("hwnd=%p, msg=0x%x\n", hWnd, message); switch (message) { case WM_PAINT: { RECT rc; SystrayItem *ptrayItem = systray;
- int top;
- EnterCriticalSection(&systray_lock);
- while (ptrayItem) {
if (ptrayItem->hWnd==hWnd) {
if (ptrayItem->notifyIcon.hIcon) { hdc = BeginPaint(hWnd, &ps); GetClientRect(hWnd, &rc);if (ptrayItem->hWnd == hWnd) {
if (!DrawIconEx(hdc, rc.left+ICON_BORDER, rc.top+ICON_BORDER, ptrayItem->notifyIcon.hIcon,
/* calculate top so we can deal with arbitrary sized trays */
top = ((rc.bottom-rc.top)/2) - ((ICON_SIZE)/2);
if (!DrawIconEx(hdc, (ICON_BORDER/2), top, ptrayItem->notifyIcon.hIcon, ICON_SIZE, ICON_SIZE, 0, 0, DI_DEFAULTSIZE|DI_NORMAL)) { ERR("Paint(SystrayWindow %p) failed -> removing SystrayItem %p\n", hWnd, ptrayItem);
} }LeaveCriticalSection(&systray_lock); SYSTRAY_Delete(&ptrayItem->notifyIcon);
@@ -97,10 +111,10 @@ ptrayItem = ptrayItem->nextTrayItem; } EndPaint(hWnd, &ps);
- LeaveCriticalSection(&systray_lock); } break;
- case WM_MOUSEMOVE: case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_RBUTTONDOWN:
@@ -110,7 +124,8 @@ { MSG msg; SystrayItem *ptrayItem = systray;
- /* relay the event to the tooltip */
- EnterCriticalSection(&systray_lock); while ( ptrayItem ) { if (ptrayItem->hWnd == hWnd) { msg.hwnd=hWnd;
@@ -125,15 +140,17 @@ } ptrayItem = ptrayItem->nextTrayItem; }
- LeaveCriticalSection(&systray_lock); }
- /* fall through */
/* fall through, so the message is sent to the callback as well */
case WM_LBUTTONDBLCLK: case WM_RBUTTONDBLCLK: case WM_MBUTTONDBLCLK: { SystrayItem *ptrayItem = systray;
- /* iterate over the currently active tray items */
- EnterCriticalSection(&systray_lock); while (ptrayItem) { if (ptrayItem->hWnd == hWnd) { if (ptrayItem->notifyIcon.hWnd && ptrayItem->notifyIcon.uCallbackMessage) {
@@ -147,9 +164,18 @@ } ptrayItem = ptrayItem->nextTrayItem; }
LeaveCriticalSection(&systray_lock); } break;
case WM_NOTIFYFORMAT:
{
TRACE("Received WM_NOTIFYFORMAT, showing the tray window\n");
ShowWindow(hWnd, SW_SHOW);
return (DefWindowProcA(hWnd, message, wParam, lParam));
}
default: return (DefWindowProcA(hWnd, message, wParam, lParam)); }
@@ -169,7 +195,7 @@ wc.hInstance = 0; wc.hIcon = 0; wc.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
- wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
- wc.hbrBackground = (HBRUSH) COLOR_WINDOW; wc.lpszMenuName = NULL; wc.lpszClassName = "WineSystray";
@@ -181,30 +207,21 @@ }
-BOOL SYSTRAY_ItemInit(SystrayItem *ptrayItem) -{ +DWORD WINAPI SYSTRAY_ThreadProc(LPVOID p1) {
- SystrayItem *ptrayItem = (SystrayItem *)p1;
- MSG msg; RECT rect;
- /* Register the class if this is our first tray item. */
- if ( firstSystray ) {
- firstSystray = FALSE;
- if ( !SYSTRAY_RegisterClass() ) {
ERR( "RegisterClass(WineSystray) failed\n" );
return FALSE;
- }
- }
- /* Initialize the window size. */ rect.left = 0; rect.top = 0; rect.right = ICON_SIZE+2*ICON_BORDER; rect.bottom = ICON_SIZE+2*ICON_BORDER;
- ZeroMemory( ptrayItem, sizeof(SystrayItem) ); /* Create tray window for icon. */ ptrayItem->hWnd = CreateWindowExA( WS_EX_TRAYWINDOW,
"WineSystray", "Wine-Systray",
WS_VISIBLE,
"WineSystray", "Windows System Tray",
0, CW_USEDEFAULT, CW_USEDEFAULT, rect.right-rect.left, rect.bottom-rect.top, 0, 0, 0, 0 );
@@ -222,31 +239,73 @@ ERR( "CreateWindow(TOOLTIP) failed\n" ); return FALSE; }
- /* Enter the message loop */
- while (GetMessageA (&msg, 0, 0, 0) > 0) {
- TranslateMessage (&msg);
- DispatchMessageA (&msg);
- }
- TRACE("Shutting down system tray thread\n");
- if(ptrayItem->notifyIcon.hIcon)
DestroyIcon(ptrayItem->notifyIcon.hIcon);
- if(ptrayItem->hWndToolTip)
DestroyWindow(ptrayItem->hWndToolTip);
- return 0;
+}
+BOOL SYSTRAY_ItemInit(SystrayItem *ptrayItem) +{
- DWORD threadID;
- /* Register the class if this is our first tray item. */
- EnterCriticalSection(&systray_lock);
- if ( firstSystray ) {
- firstSystray = FALSE;
- if ( !SYSTRAY_RegisterClass() ) {
ERR( "RegisterClass(WineSystray) failed\n" );
LeaveCriticalSection(&systray_lock);
return FALSE;
- }
- }
- LeaveCriticalSection(&systray_lock);
- ZeroMemory( ptrayItem, sizeof(SystrayItem) );
- /* We need to run the system tray window in a separate thread, as otherwise if the originating thread
stops processing messages, the tray window will hang. If another part of the application then does
for instance a FindWindow call, this can deadlock the application. */
- if (!CreateThread(NULL, 0, SYSTRAY_ThreadProc, (LPVOID) ptrayItem, 0, &threadID)) {
- ERR("Could not create system tray item thread\n");
- return FALSE;
- } return TRUE;
}
static void SYSTRAY_ItemTerm(SystrayItem *ptrayItem) {
- if(ptrayItem->notifyIcon.hIcon)
DestroyIcon(ptrayItem->notifyIcon.hIcon);
- if(ptrayItem->hWndToolTip)
DestroyWindow(ptrayItem->hWndToolTip);
- if(ptrayItem->hWnd)
- DestroyWindow(ptrayItem->hWnd);
- /* MSDN says we shouldn't do this, but I can't see another way to make GetMessage() return zero */
- PostMessageA(ptrayItem->hWnd, WM_QUIT, 0, 0); return;
}
void SYSTRAY_ItemSetMessage(SystrayItem *ptrayItem, UINT uCallbackMessage) {
- EnterCriticalSection(&systray_lock); ptrayItem->notifyIcon.uCallbackMessage = uCallbackMessage;
- LeaveCriticalSection(&systray_lock);
}
void SYSTRAY_ItemSetIcon(SystrayItem *ptrayItem, HICON hIcon) {
- EnterCriticalSection(&systray_lock); ptrayItem->notifyIcon.hIcon = CopyIcon(hIcon);
- LeaveCriticalSection(&systray_lock);
- InvalidateRect(ptrayItem->hWnd, NULL, TRUE);
}
@@ -255,9 +314,11 @@ { TTTOOLINFOA ti;
- strncpy(ptrayItem->notifyIcon.szTip, szTip, sizeof(ptrayItem->notifyIcon.szTip));
- EnterCriticalSection(&systray_lock);
- strncpy(ptrayItem->notifyIcon.szTip, szTip, sizeof(ptrayItem->notifyIcon.szTip)); ptrayItem->notifyIcon.szTip[sizeof(ptrayItem->notifyIcon.szTip)-1]=0;
- LeaveCriticalSection(&systray_lock);
- ti.cbSize = sizeof(TTTOOLINFOA); ti.uFlags = 0; ti.hwnd = ptrayItem->hWnd;
@@ -280,10 +341,15 @@ { SystrayItem **ptrayItem = &systray;
- TRACE("%p\n", pnid);
- EnterCriticalSection(&systray_lock); /* Find last element. */ while( *ptrayItem ) {
- if ( SYSTRAY_ItemIsEqual(pnid, &(*ptrayItem)->notifyIcon) )
- if ( SYSTRAY_ItemIsEqual(pnid, &(*ptrayItem)->notifyIcon) ) {
LeaveCriticalSection(&systray_lock); return FALSE;
- } ptrayItem = &((*ptrayItem)->nextTrayItem); } /* Allocate SystrayItem for element and add to end of list. */
@@ -297,6 +363,7 @@ SYSTRAY_ItemSetMessage(*ptrayItem, (pnid->uFlags&NIF_MESSAGE)?pnid->uCallbackMessage:0); SYSTRAY_ItemSetTip (*ptrayItem, (pnid->uFlags&NIF_TIP) ?pnid->szTip :"", FALSE);
- LeaveCriticalSection(&systray_lock); TRACE("%p: %p %s\n", (*ptrayItem), (*ptrayItem)->notifyIcon.hWnd, (*ptrayItem)->notifyIcon.szTip); return TRUE;
@@ -307,8 +374,12 @@ { SystrayItem *ptrayItem = systray;
- TRACE("%p\n", pnid);
- EnterCriticalSection(&systray_lock); while ( ptrayItem ) { if ( SYSTRAY_ItemIsEqual(pnid, &ptrayItem->notifyIcon) ) {
LeaveCriticalSection(&systray_lock); if (pnid->uFlags & NIF_ICON) SYSTRAY_ItemSetIcon(ptrayItem, pnid->hIcon); if (pnid->uFlags & NIF_MESSAGE)
@@ -321,6 +392,7 @@ } ptrayItem = ptrayItem->nextTrayItem; }
- LeaveCriticalSection(&systray_lock); return FALSE; /* not found */
}
@@ -329,6 +401,9 @@ { SystrayItem **ptrayItem = &systray;
- TRACE("%p\n", pnid);
- EnterCriticalSection(&systray_lock); while (*ptrayItem) { if (SYSTRAY_ItemIsEqual(pnid, &(*ptrayItem)->notifyIcon)) { SystrayItem *next = (*ptrayItem)->nextTrayItem;
@@ -338,10 +413,12 @@ free(*ptrayItem); *ptrayItem = next;
LeaveCriticalSection(&systray_lock); return TRUE;
} ptrayItem = &((*ptrayItem)->nextTrayItem); }
LeaveCriticalSection(&systray_lock);
return FALSE; /* not found */
} Index: dlls/x11drv/event.c =================================================================== RCS file: /home/wine/wine/dlls/x11drv/event.c,v retrieving revision 1.29 diff -u -r1.29 event.c --- dlls/x11drv/event.c 21 Nov 2003 21:48:36 -0000 1.29 +++ dlls/x11drv/event.c 30 Nov 2003 16:08:37 -0000 @@ -3,6 +3,7 @@
- Copyright 1993 Alexandre Julliard
1999 Noel Borthwick
2003 Mike Hearn
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
@@ -51,10 +52,15 @@
WINE_DEFAULT_DEBUG_CHANNEL(event); WINE_DECLARE_DEBUG_CHANNEL(clipboard); +WINE_DECLARE_DEBUG_CHANNEL(systray);
/* X context to associate a hwnd to an X window */ extern XContext winContext;
+extern Atom systray_selection; +extern Window systray_window;
#define DndNotDnd -1 /* OffiX drag&drop */ #define DndUnknown 0 #define DndRawData 1 @@ -1213,7 +1219,47 @@ static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event ) { if (event->message_type != None && event->format == 32) {
- if (event->message_type == x11drv_atom(WM_PROTOCOLS))
- if (event->message_type == x11drv_atom(MANAGER)) {
- if (event->data.l[1] == systray_selection) {
TRACE_(systray)("New NETWM systray manager detected, id=%ld\n", event->data.l[2]);
/* NOTE: It turns out that the ability to detect when a new tray applet joins the
* desktop is not as helpful as you might think. In order to do something useful with it,
* we would need to be able to "store" icons unmapped as children of the root window while
* no tray applet is available.
*
* The basic problem is that tray icons are always destroyed when the applet is removed.
* This is apparently an issue with X itself, which the upcoming XFIXES extension should hopefully
* address. The EggTrayIcon code which will be soon moving into GTK+ doesn't attempt to handle this
* situation, so for now neither do we.
*
* This is theoretically fixable in Wine with enough work, we just have to modify the code in
* shell32/systray.c to save the image and recreate the window on demand. Exactly how the
* communication between the x11drv and shell32 takes place is left as an excercise for the
* reader.
* -mike (3rd August 2003)
*/
- }
- } else if (event->message_type == x11drv_atom(_XEMBED)) {
char* opcode;
- switch (event->data.l[1]) {
case 0: opcode = "XEMBED_EMBEDDED_NOTIFY"; break;
case 1: opcode = "XEMBED_WINDOW_ACTIVATE"; break;
case 2: opcode = "XEMBED_WINDOW_DEACTIVATE"; break;
case 3: opcode = "XEMBED_REQUEST_FOCUS"; break;
case 4: opcode = "XEMBED_FOCUS_IN"; break;
case 5: opcode = "XEMBED_FOCUS_OUT"; break;
case 6: opcode = "XEMBED_FOCUS_NEXT"; break;
case 7: opcode = "XEMEBD_FOCUS_PREV"; break;
case 10: opcode = "XEMBED_MODALITY_ON"; break;
case 11: opcode = "XEMBED_MODALITY_OFF"; break;
case 12: opcode = "XEMBED_REGISTER_ACCELERATOR"; break;
case 13: opcode = "XEMBED_UNREGISTER_ACCELERATOR"; break;
case 14: opcode = "XEMBED_ACTIVATE_ACCELERATOR"; break;
default: opcode = "[Unknown opcode]"; break;
- }
TRACE_(systray)("XEmbed message, opcode is %s : %ld\n", opcode, event->data.l[1]);
- /* we currently don't handle these messages */
- } else if (event->message_type == x11drv_atom(WM_PROTOCOLS)) handle_wm_protocols_message( hWnd, event ); else if (event->message_type == x11drv_atom(DndProtocol)) {
Index: dlls/x11drv/window.c
RCS file: /home/wine/wine/dlls/x11drv/window.c,v retrieving revision 1.65 diff -u -r1.65 window.c --- dlls/x11drv/window.c 21 Nov 2003 21:48:36 -0000 1.65 +++ dlls/x11drv/window.c 30 Nov 2003 16:08:37 -0000 @@ -4,6 +4,7 @@
- Copyright 1993, 1994, 1995, 1996, 2001 Alexandre Julliard
- Copyright 1993 David Metcalfe
- Copyright 1995, 1996 Alex Korobka
- Copyright 2003 Mike Hearn
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
@@ -24,6 +25,7 @@
#include <stdarg.h> #include <stdlib.h> +#include <stdio.h> #ifdef HAVE_UNISTD_H # include <unistd.h> #endif @@ -46,6 +48,7 @@ #include "mwm.h"
WINE_DEFAULT_DEBUG_CHANNEL(x11drv); +WINE_DECLARE_DEBUG_CHANNEL(systray);
extern Pixmap X11DRV_BITMAP_Pixmap( HBITMAP );
@@ -73,6 +76,7 @@ "WM_PROTOCOLS", "WM_DELETE_WINDOW", "WM_TAKE_FOCUS",
- "MANAGER", "KWM_DOCKWINDOW", "DndProtocol", "DndSelection",
@@ -81,6 +85,9 @@ "_NET_WM_PID", "_NET_WM_PING", "_NET_WM_NAME",
- "_XEMBED_INFO",
- "_XEMBED",
- "_NET_SYSTEM_TRAY_OPCODE", "XdndAware", "XdndEnter", "XdndPosition",
@@ -103,6 +110,14 @@ "text/richtext" };
+/* for XDG systray icons */ +Atom systray_selection; +Window systray_window; +#define SYSTEM_TRAY_REQUEST_DOCK 0 +#define SYSTEM_TRAY_BEGIN_MESSAGE 1 +#define SYSTEM_TRAY_CANCEL_MESSAGE 2
static LPCSTR whole_window_atom; static LPCSTR client_window_atom; static LPCSTR icon_window_atom; @@ -354,11 +369,60 @@ size_hints->min_height = size_hints->max_height; size_hints->flags |= PMinSize | PMaxSize; }
- if (win->dwExStyle & WS_EX_TRAYWINDOW) {
/* force the window to be the correct width */
size_hints->min_width = GetSystemMetrics(SM_CXSMICON) + 5; /* give some padding to make icons not bunched up */
- }
}XSetWMNormalHints( display, data->whole_window, size_hints ); XFree( size_hints );
}
+/***********************************************************************
X11DRV_systray_dock_window
- Docks the given X window with the NETWM system tray.
- */
+BOOL CALLBACK X11DRV_systray_dock_window( HWND hwnd, Display *display ) {
- WND* win = WIN_GetPtr((HWND)hwnd);
- struct x11drv_win_data *data = win->pDriverData;
- XEvent ev;
- unsigned long info[2];
- LONG exstyle;
- /* is the window a tray window? */
- if (IsWindowUnicode(hwnd))
- exstyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
- else
- exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
- if ( !(exstyle & WS_EX_TRAYWINDOW) ) return TRUE;
- TRACE_(systray)("Docking tray icon 0x%x\n", (int)hwnd);
- /* set XEMBED protocol data on the window */
- info[0] = 0; /* protocol version */
- info[1] = 0; /* mapped = true */
- XChangeProperty(display, data->whole_window, x11drv_atom(_XEMBED_INFO), x11drv_atom(_XEMBED_INFO), 32, PropModeReplace, (unsigned char*)info, 2);
- /* send the docking request message */
- memset(&ev, 0, sizeof(ev));
- ev.xclient.type = ClientMessage;
- ev.xclient.window = systray_window;
- ev.xclient.message_type = x11drv_atom(_NET_SYSTEM_TRAY_OPCODE);
- ev.xclient.format = 32;
- ev.xclient.data.l[0] = CurrentTime;
- ev.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK;
- ev.xclient.data.l[2] = data->whole_window;
- XSendEvent(display, systray_window, False, NoEventMask, &ev);
- XSync(display, False);
- WIN_ReleasePtr(win);
- return TRUE;
+}
/***********************************************************************
X11DRV_set_wm_hints
@@ -408,7 +472,7 @@ set_size_hints( display, win );
/* systray properties (KDE only for now) */
- if (win->dwExStyle & WS_EX_TRAYWINDOW)
- if ((win->dwExStyle & WS_EX_TRAYWINDOW) && (systray_window == None)) { int val = 1; XChangeProperty( display, data->whole_window, x11drv_atom(KWM_DOCKWINDOW),
@@ -709,10 +773,19 @@ static void create_desktop( Display *display, WND *wndPtr ) { X11DRV_WND_DATA *data = wndPtr->pDriverData;
char *systray_buffer;
wine_tsx11_lock(); winContext = XUniqueContext(); XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
/* we can't intern this with the rest as it depends on the screen we are connecting to */
systray_buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(char)*20);
sprintf(systray_buffer, "_NET_SYSTEM_TRAY_S%d", DefaultScreen(display));
systray_selection = XInternAtom(display, systray_buffer, False);
HeapFree(GetProcessHeap(), 0, systray_buffer);
wine_tsx11_unlock();
whole_window_atom = MAKEINTATOMA( GlobalAddAtomA( "__wine_x11_whole_window" ));
@@ -1109,6 +1182,14 @@ * we do a proper ShowWindow later on */ if (wndPtr->dwStyle & WS_VISIBLE) cs->style |= WS_VISIBLE;
- /* if it's a tray window, dock it */
- if (wndPtr->dwExStyle & WS_EX_TRAYWINDOW) {
/* get the tray window if present */
systray_window = XGetSelectionOwner(display, systray_selection);
if (systray_window != None)
- X11DRV_systray_dock_window(hwnd, display);
- }
- WIN_ReleaseWndPtr( wndPtr ); return TRUE;
Index: dlls/x11drv/x11drv.h
RCS file: /home/wine/wine/dlls/x11drv/x11drv.h,v retrieving revision 1.11 diff -u -r1.11 x11drv.h --- dlls/x11drv/x11drv.h 25 Nov 2003 03:27:38 -0000 1.11 +++ dlls/x11drv/x11drv.h 30 Nov 2003 16:08:37 -0000 @@ -387,6 +387,7 @@ XATOM_WM_PROTOCOLS, XATOM_WM_DELETE_WINDOW, XATOM_WM_TAKE_FOCUS,
- XATOM_MANAGER, XATOM_KWM_DOCKWINDOW, XATOM_DndProtocol, XATOM_DndSelection,
@@ -395,6 +396,9 @@ XATOM__NET_WM_PID, XATOM__NET_WM_PING, XATOM__NET_WM_NAME,
- XATOM__XEMBED_INFO,
- XATOM__XEMBED,
- XATOM__NET_SYSTEM_TRAY_OPCODE, XATOM_XdndAware, XATOM_XdndEnter, XATOM_XdndPosition,
Mike Hearn mike@theoretic.com writes:
This has missed the last two commits. Is this codes presence in shell32 really a blocking issue? If so then I'd note that quite a lot of people have problems caused by the lack of this patch (can't quit apps etc).
That's why it needs to be fixed properly. If you just hide the symptoms no one will bother to do the right fix.
On Thu, 2003-12-04 at 21:32, Alexandre Julliard wrote:
That's why it needs to be fixed properly. If you just hide the symptoms no one will bother to do the right fix.
Well, there are many areas of Wine where we have code in different places to Windows, so I don't really agree that this patch is wrong. But, if you insist, then I guess we need a new program.
I guess it should perform the tasks that explorer.exe would normally perform in Windows, ie system tray integration (obviously) and progman groups/menu integration? I'm not really sure how that'd work.
Hmm, two things. Have I missed anything? Maybe the clipboard server thing could be integrated with it, but modern desktops cache X selections anyway (or will do soon) so I'm not even sure that's still needed. Do we really need a new program for only two things?
Mike Hearn mike@theoretic.com writes:
Hmm, two things. Have I missed anything? Maybe the clipboard server thing could be integrated with it, but modern desktops cache X selections anyway (or will do soon) so I'm not even sure that's still needed. Do we really need a new program for only two things?
Yes, we need a process context for these things. We can't go about creating new threads in every process every time we need to process messages, especially when there is state that needs to be maintained across processes anyway.