void emX11WindowPort::SetPosSize( double x, double y, PosSizeArgSpec posSpec, double w, double h, PosSizeArgSpec sizeSpec ) { if ((GetWindowFlags()&emWindow::WF_FULLSCREEN)!=0) { posSpec=PSAS_IGNORE; sizeSpec=PSAS_IGNORE; } if (posSpec==PSAS_IGNORE) { x=GetViewX(); y=GetViewY(); } else { if (posSpec==PSAS_WINDOW) { x+=BorderL; y+=BorderT; } x=floor(x+0.5); y=floor(y+0.5); PosForced=true; PosPending=true; } if (sizeSpec==PSAS_IGNORE) { w=GetViewWidth(); h=GetViewHeight(); } else { if (sizeSpec==PSAS_WINDOW) { w-=BorderL+BorderR; h-=BorderT+BorderB; } w=floor(w+0.5); h=floor(h+0.5); if (w<MinPaneW) w=MinPaneW; if (h<MinPaneH) h=MinPaneH; SizeForced=true; SizePending=true; } SetViewGeometry(x,y,w,h,Screen.PixelTallness); WakeUp(); }
void C4Viewport::DropFile(const char* fileName, float x, float y) { Game.DropFile(fileName, GetViewX()+x/Zoom, GetViewY()+y/Zoom); }
bool emX11WindowPort::Cycle() { XWindowAttributes attr; XSizeHints xsh; emString str; emCursor cur; ::Window win; ::Cursor xcur; emX11WindowPort * wp; double vrx,vry,vrw,vrh,fx,fy,fw,fh; int i,x,y,w,h; Status xs; if ( FullscreenUpdateTimer && IsSignaled(FullscreenUpdateTimer->GetSignal()) ) { Screen.GetVisibleRect(&vrx,&vry,&vrw,&vrh); if ( fabs(PaneX-vrx)>0.51 || fabs(PaneY-vry)>0.51 || fabs(PaneW-vrw)>0.51 || fabs(PaneH-vrh)>0.51 ) { PosForced=true; PosPending=true; SizeForced=true; SizePending=true; SetViewGeometry(vrx,vry,vrw,vrh,Screen.PixelTallness); } // Workaround for lots of focus problems with several window managers: if (Screen.GrabbingWinPort==this) { XMutex.Lock(); XGetInputFocus(Disp,&win,&i); XMutex.Unlock(); wp=NULL; for (i=Screen.WinPorts.GetCount()-1; i>=0; i--) { if (Screen.WinPorts[i]->Win==win) { wp=Screen.WinPorts[i]; break; } } if (wp==this) { if (!Focused) { Focused=true; SetViewFocused(true); emWarning("emX11WindowPort: Focus workaround 1 applied."); } } else { while (wp) { if (wp==this) break; wp=wp->Owner; } if (!wp) { XMutex.Lock(); xs=XGetWindowAttributes(Disp,Win,&attr); XMutex.Unlock(); if (xs && attr.map_state==IsViewable) { XMutex.Lock(); XSetInputFocus(Disp,Win,RevertToNone,CurrentTime); XMutex.Unlock(); emWarning("emX11WindowPort: Focus workaround 2 applied."); } } } } } if ( !PostConstructed && !PosForced && Owner && (GetWindowFlags()&emWindow::WF_FULLSCREEN)==0 ) { Screen.GetVisibleRect(&vrx,&vry,&vrw,&vrh); fx=Owner->GetViewX()-Owner->BorderL; fy=Owner->GetViewY()-Owner->BorderT; fw=Owner->GetViewWidth()+Owner->BorderL+Owner->BorderR; fh=Owner->GetViewHeight()+Owner->BorderT+Owner->BorderB; fx+=fw*0.5; fy+=fh*0.5; fw=GetViewWidth()+BorderL+BorderR; fh=GetViewHeight()+BorderT+BorderB; fx-=fw*0.5+emGetDblRandom(-0.03,0.03)*vrw; fy-=fh*0.5+emGetDblRandom(-0.03,0.03)*vrh; if (fx>vrx+vrw-fw) fx=vrx+vrw-fw; if (fy>vry+vrh-fh) fy=vry+vrh-fh; if (fx<vrx) fx=vrx; if (fy<vry) fy=vry; SetViewGeometry( fx+BorderL,fy+BorderT, GetViewWidth(),GetViewHeight(), Screen.PixelTallness ); PosPending=true; PosForced=true; } if (PosPending || SizePending) { x=((int)GetViewX())-BorderL; y=((int)GetViewY())-BorderT; w=(int)GetViewWidth(); h=(int)GetViewHeight(); memset(&xsh,0,sizeof(xsh)); xsh.flags =PMinSize; xsh.min_width =MinPaneW; xsh.min_height=MinPaneH; if (PosForced) { xsh.flags|=PPosition|USPosition; xsh.x=x; xsh.y=y; } if (SizeForced) { xsh.flags|=PSize|USSize; xsh.width=w; xsh.height=h; } XMutex.Lock(); XSetWMNormalHints(Disp,Win,&xsh); if (PosPending && SizePending) { XMoveResizeWindow(Disp,Win,x,y,w,h); } else if (PosPending) { XMoveWindow(Disp,Win,x,y); } else { XResizeWindow(Disp,Win,w,h); } XMutex.Unlock(); PosPending=false; SizePending=false; } if (TitlePending) { str=GetWindowTitle(); if (Title!=str) { Title=str; XMutex.Lock(); XmbSetWMProperties(Disp,Win,Title.Get(),NULL,NULL,0,NULL,NULL,NULL); XMutex.Unlock(); } TitlePending=false; } if (IconPending) { SetIconProperty(GetWindowIcon()); IconPending=false; } if (CursorPending) { cur=GetViewCursor(); if (Cursor!=cur) { Cursor=cur; xcur=Screen.GetXCursor(cur); XMutex.Lock(); XDefineCursor(Disp,Win,xcur); XMutex.Unlock(); } CursorPending=false; } if (!PostConstructed) { PostConstruct(); PostConstructed=true; } if (!InvalidRects.IsEmpty() && Mapped) { UpdatePainting(); if (!LaunchFeedbackSent) { LaunchFeedbackSent=true; SendLaunchFeedback(); } } return false; }
void emX11WindowPort::HandleEvent(XEvent & event) { emInputEvent inputEvent; emX11WindowPort * wp; char tmp[256]; char keymap[32]; KeySym ks; emInputKey key; Status status; int i,x,y,w,h,mask,repeat,variant,len; double mx,my; bool inside; // Remember: // - Calling InputToView may delete this window port. // - The grab stuff is very very tricky. switch (event.type) { case MotionNotify: mx=PaneX+event.xmotion.x+Screen.MouseWarpX; my=PaneY+event.xmotion.y+Screen.MouseWarpY; if ( Screen.InputState.GetMouseX()!=mx || Screen.InputState.GetMouseY()!=my ) { Screen.InputState.SetMouse(mx,my); Screen.InputStateClock++; } for (i=0; i<3; i++) { if (i==0) { key=EM_KEY_LEFT_BUTTON ; mask=Button1Mask; } else if (i==1) { key=EM_KEY_MIDDLE_BUTTON; mask=Button2Mask; } else { key=EM_KEY_RIGHT_BUTTON ; mask=Button3Mask; } if (Screen.InputState.Get(key) && (event.xmotion.state&mask)==0) { Screen.InputState.Set(key,false); Screen.InputStateClock++; } } return; case ButtonPress: mx=PaneX+event.xbutton.x+Screen.MouseWarpX; my=PaneY+event.xbutton.y+Screen.MouseWarpY; if ( Screen.InputState.GetMouseX()!=mx || Screen.InputState.GetMouseY()!=my ) { Screen.InputState.SetMouse(mx,my); Screen.InputStateClock++; } wp=SearchOwnedPopupAt(mx,my); if (wp) { if (wp->Mapped) { event.xbutton.x+=PaneX-wp->PaneX; event.xbutton.y+=PaneY-wp->PaneY; wp->HandleEvent(event); } return; } if (ModalDescendants>0) { FocusModalDescendant(true); return; } inside=( mx>=PaneX && mx<PaneX+PaneW && my>=PaneY && my<PaneY+PaneH ); if ( !inside && Screen.GrabbingWinPort==this && (GetWindowFlags()&emWindow::WF_POPUP)!=0 ) { XMutex.Lock(); XAllowEvents(Disp,ReplayPointer,CurrentTime); XMutex.Unlock(); Screen.GrabbingWinPort=NULL; LastButtonPress=EM_KEY_NONE; SignalWindowClosing(); } for (i=Screen.WinPorts.GetCount()-1; i>=0; i--) { wp=Screen.WinPorts[i]; if ( (wp->GetWindowFlags()&emWindow::WF_POPUP)!=0 && wp!=this && !wp->IsAncestorOf(this) ) { wp->SignalWindowClosing(); } } if (!inside) return; if (!Focused && event.xbutton.button>=1 && event.xbutton.button<=5) { RequestFocus(); Screen.UpdateKeymapAndInputState(); } if (event.xbutton.button>=1 && event.xbutton.button<=3) { if (event.xbutton.button==1) key=EM_KEY_LEFT_BUTTON; else if (event.xbutton.button==2) key=EM_KEY_MIDDLE_BUTTON; else key=EM_KEY_RIGHT_BUTTON; if (!Screen.InputState.Get(key)) { Screen.InputState.Set(key,true); Screen.InputStateClock++; if ( key==LastButtonPress && event.xbutton.time>LastButtonPressTime && event.xbutton.time-LastButtonPressTime<=330 && event.xbutton.x>=LastButtonPressX-10 && event.xbutton.x<=LastButtonPressX+10 && event.xbutton.y>=LastButtonPressY-10 && event.xbutton.y<=LastButtonPressY+10 ) { repeat=LastButtonPressRepeat+1; } else { repeat=0; } LastButtonPress=key; LastButtonPressTime=event.xbutton.time; LastButtonPressX=event.xbutton.x; LastButtonPressY=event.xbutton.y; LastButtonPressRepeat=repeat; inputEvent.Setup(key,"",repeat,0); InputStateClock=Screen.InputStateClock; InputToView(inputEvent,Screen.InputState); return; } } else if (event.xbutton.button==4) { inputEvent.Setup(EM_KEY_WHEEL_UP,"",0,0); InputStateClock=Screen.InputStateClock; InputToView(inputEvent,Screen.InputState); return; } else if (event.xbutton.button==5) { inputEvent.Setup(EM_KEY_WHEEL_DOWN,"",0,0); InputStateClock=Screen.InputStateClock; InputToView(inputEvent,Screen.InputState); return; } return; case ButtonRelease: mx=PaneX+event.xbutton.x+Screen.MouseWarpX; my=PaneY+event.xbutton.y+Screen.MouseWarpY; if ( Screen.InputState.GetMouseX()!=mx || Screen.InputState.GetMouseY()!=my ) { Screen.InputState.SetMouse(mx,my); Screen.InputStateClock++; } if (event.xbutton.button>=1 && event.xbutton.button<=3) { if (event.xbutton.button==1) key=EM_KEY_LEFT_BUTTON; else if (event.xbutton.button==2) key=EM_KEY_MIDDLE_BUTTON; else key=EM_KEY_RIGHT_BUTTON; if (Screen.InputState.Get(key)) { Screen.InputState.Set(key,false); Screen.InputStateClock++; inputEvent.Eat(); InputStateClock=Screen.InputStateClock; InputToView(inputEvent,Screen.InputState); return; } } return; case KeyPress: i=event.xkey.keycode/8; mask=1<<(event.xkey.keycode&7); if (i<32 && (Screen.Keymap[i]&mask)==0) { Screen.Keymap[i]|=mask; Screen.UpdateInputStateFromKeymap(); } if (InputContext) { XMutex.Lock(); len=XmbLookupString( InputContext, &event.xkey, tmp, sizeof(tmp)-1, &ks, &status ); XMutex.Unlock(); if (status!=XLookupChars && status!=XLookupBoth) len=0; if (status!=XLookupKeySym && status!=XLookupBoth) ks=0; } else { XMutex.Lock(); len=XLookupString( &event.xkey, tmp, sizeof(tmp)-1, &ks, &ComposeStatus ); XMutex.Unlock(); } tmp[len]=0; key=emX11Screen::ConvertKey(ks,&variant); if (key==EM_KEY_NONE && !tmp[0]) return; repeat=0; if ( key!=EM_KEY_NONE && Screen.InputState.Get(key) && RepeatKey==key ) { repeat=KeyRepeat+1; } if (ModalDescendants>0) return; RepeatKey=key; KeyRepeat=repeat; inputEvent.Setup(key,tmp,repeat,variant); InputStateClock=Screen.InputStateClock; InputToView(inputEvent,Screen.InputState); return; case KeyRelease: memset(keymap,0,sizeof(keymap)); XMutex.Lock(); XQueryKeymap(Disp,keymap); XMutex.Unlock(); i=event.xkey.keycode/8; mask=1<<(event.xkey.keycode&7); if (i<32 && (keymap[i]&mask)==0) { RepeatKey=EM_KEY_NONE; if ((Screen.Keymap[i]&mask)!=0) { Screen.Keymap[i]&=~mask; Screen.UpdateInputStateFromKeymap(); } } return; case Expose: x=event.xexpose.x; y=event.xexpose.y; w=event.xexpose.width; h=event.xexpose.height; InvalidatePainting(PaneX+x,PaneY+y,w,h); return; case FocusIn: if ( event.xfocus.mode==NotifyNormal || event.xfocus.mode==NotifyWhileGrabbed ) { if (InputContext) { XMutex.Lock(); XSetICFocus(InputContext); XMutex.Unlock(); } Screen.UpdateKeymapAndInputState(); RepeatKey=EM_KEY_NONE; if (!Focused) { Focused=true; SetViewFocused(true); } if (ModalDescendants>0) FocusModalDescendant(); } return; case FocusOut: if ( event.xfocus.mode==NotifyNormal || event.xfocus.mode==NotifyWhileGrabbed ) { if (InputContext) { XMutex.Lock(); XUnsetICFocus(InputContext); XMutex.Unlock(); } if (Focused) { Focused=false; SetViewFocused(false); } LastButtonPress=EM_KEY_NONE; RepeatKey=EM_KEY_NONE; } return; case ConfigureNotify: // The meaning of the coordinates from event.xconfigure depends on // the window manager. Therefore: GetAbsWinGeometry(Disp,Win,&x,&y,&w,&h); if (PaneX!=x || PaneY!=y || PaneW!=w || PaneH!=h) { PaneX=x; PaneY=y; PaneW=w; PaneH=h; ClipX1=PaneX; ClipY1=PaneY; ClipX2=PaneX+PaneW; ClipY2=PaneY+PaneH; InvalidRects.Set(PaneX,PaneY,PaneX+PaneW,PaneY+PaneH); WakeUp(); if (!PosPending && !SizePending) { SetViewGeometry( PaneX,PaneY, PaneW,PaneH, Screen.PixelTallness ); } else if (!PosPending) { SetViewGeometry( PaneX,PaneY, GetViewWidth(),GetViewHeight(), Screen.PixelTallness ); } else if (!SizePending) { SetViewGeometry( GetViewX(),GetViewY(), PaneW,PaneH, Screen.PixelTallness ); } Screen.InputStateClock++; } return; case MapNotify: if (event.xmap.window==Win && !Mapped) { Mapped=true; WakeUp(); } return; case UnmapNotify: if (event.xmap.window==Win && Mapped) { Mapped=false; } return; case ClientMessage: if (event.xclient.data.l[0]==(long)Screen.WM_DELETE_WINDOW) { if (ModalDescendants<=0) SignalWindowClosing(); else FocusModalDescendant(true); } return; } }